Hash课堂笔记
Hash哈希笔记
概念
-
Hash就是吧一个字母映射成一个数字(树,图,字符串都可映射)
-
通过映射的 Hash值 进行比较。
-
在映射 Hash值 可能会发生冲突,即不同字符串映射成一样的\(Hash\)值。失效。
-
对于字符串来说,我们常把字符串看成K进制数(k>26,k为质数!!),然后对一个大指数取摸,余数就是此字符串的 Hash值 。
-
有时也用自然溢出为代价加快效率。
判断字串是否相同
-
题面
-
给出一个字付串,每次询问两个字串是否相同
1.预处理
先预设要模的大质数和位进制;
ll base = 131;
ll mod = 2123400401301379571;
之后对每个字串进行Hash预处理运算
for(int i = 1;i <= n; i++)
hs[i] = (hs[i-1] * base+idx(s[i]))%mod;//idx(sp[i]):第s[i]个字符所映射的数字
预处理\(\ power\)数组, (\(\ power[i]\) 表示当前 \(k\) 进制下,\(k\) 的 \(i\) 次方)
power[0] = 1;
for(int i = 1;i <= n; i++){
(ll)power[i]=(ll)power[i-1]*k%mod;//%mod是减少预算量,否组数会特别大
}
举例( \(10\) 进制)
\(2345\),我只要 \(345\) ,那么就需要 \({2345-2000 = 2\times 10^3 +3\times 10^2+4\times 10^1+5\times 10^0 - 2\times 10^3}\)
由上述预处理可知,现在我们哈希数组 \(ha[]\) 中的数分别为
\[\begin{alignedat}{3}
ha[1] & = 2\times10^0 \ 即2\\
ha[2] & = 2 \ \times10^1+3 \ \times10^0 \ 即23\\
ha[3] & = 2 \ \times10^2+3 \ \times10^1+4 \ \times10^0 \ 即234\\
ha[4] & = 2 \ \times10^3+3 \ \times10^2+4 \ \times10^1+5 \ \times10^0\ 即2345\\
\end{alignedat}
\]
那么 \(后三位的字符应该是=2345-2000=345=ha[4]-ha[(2-1)]\times 10^{(4-2+1)}\) ;
同理 \(45 = ha[4] - ha[2]\times 10^{(4-3+1)}\)
那么 \(K\) 进制数也是如此,因此就有了下面的公式。
// l r 表示需要的区间的字符边界
int hash_interval(int l,int r){
ans = ((ll)ha[r] - (ll)ha[l - 1]*power[r - l + 1]%mod+mod)%mod
//power[i]:k进制数的i次方.
//最后+mod是防止负数,原理不会变。
}
再有,对上面公式的推论举个例子,方便以后复习和外人观看更好理解
举例
-
\(a,b,c,d,a\)
-
\(1,2,3,4,1\)
-
进制:29,\((ll)mod\ :\ 2123400401301379571\)
\[\begin{alignedat}{3}
ha[1] & = 1\times29^0(1) \\
ha[2] & = 1 \ \times29^1+2 \ \times29^0(12) \\
ha[3] & = 1 \ \times29^2+2 \ \times29^1+3 \ \times29^0(123)\\
ha[4] & = 1 \ \times29^3+2 \ \times29^2+3 \ \times29^1+4 \ \times29^0(1234)\\
...\\
\end{alignedat}
\]
- 求 \(ha[3-4]\)
\[\begin{alignedat}{3}
ha[3-4]& = ha[4]-ha[2]\times29^2(34) \\
&=1234-1200(12\times 29^2)\\
& = 34
\end{alignedat}
\]
注:我是用10进制进行举例,方便~
作者@Thorzy,转载请声明出处