Hash


思想:把字符串变成数值比较。

我们选取这个 hash 公式:

\[hash(s)=\sum_{i=1}^{len} s_i\times p^{len-i}(mod\ M) \]

hash方法

自然溢出hash

我们使用

unsigned long long hash[N];

\(hash[k]\))来存储一个字符串下标 \([1,k]\) 的 hash 值

hash 公式就是:

\[hash(s_{1,len})=hash(s_{1,len-1})\times p + s_{len} \]

我们知道 unsigned long long 在数值过大的时候会自动对 \(2^{64}\) 取模

单hash

采用一个一大一小两个素数

hash 公式:

\[hash(s_{1,len})=(hash(s_{1,len-1})\times p + s_{len})\%M \]

hash 冲突的概率不高

双hash

取两不同的模数分别hash

hash 公式:

\[hash_1(s_{1,len})=(hash_1(s_{1,len-1})\times p + s_{len})\%M_1 \]

\[hash_2(s_{1,len})=(hash_2(s_{1,len-1})\times p + s_{len})\%M_2 \]

然后取 \(make\_pair(\ hash_1(s),hash_2(s)\ )\) 作为 hash 值

求子串hash值

公式:

\[hash(s_{l,r})=((hash(s_{1,r})-hash(s_{1,l-1}))\times p^{r-l+1})\%M+M)\%M \]

差分思想,很好理解(注意减法可能出现负数)

\(p^{r-l+1}\) 是为了能抵消无关字符的 hash 值。

举个例子:

\[hash(s_{1,1})=s_1 \]

\[hash(s_{1,2})=s_1\times p + s_2 \]

\[hash(s_{1,3})=s_1\times p^{2} + s_2\times p + s_3 \]

算一算\(hash(s_{2,3})\)大概就能理解了。