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