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})$大概就能理解了。