字符串哈希(详解+模版)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luyehao1/article/details/84930513

参考博客:

详解1

详解2

详解3

个人理解:

字符串Hash的种类还是有很多种的,不过在ACM中一般只会用到一种名为“BKDR Hash”的字符串Hash算法。它的主要思路是选取恰当的进制,可以把字符串中的字符看成一个大数字中的每一位数字。关于进制的选择实际上非常自由,大于所有字符对应的数字的最大值即可,比如一个字符集是a到z的题目,选择27、233、19260817都是可以的。一般使用李煜东前辈的给出的值——131或13331,此时冲突概率极低

使用哈希数组Hash[i]保存前缀:一般设Hash[0]=0 。

Hash[i]=s[1]*P^{i-1}+s[2]*P^{i-2}+s[3]*P^{i-3}+...+s[i]

=>

Hash[0] = 0

Hash[1] = s[1]

Hash[2] = s[1]*P+s[2]

Hash[3] = s[1]*P^{2} + s[2]*P+s[3]

Hash[4] = s[1]*P^{3} + s[2]*P^{2}+s[3]*P+s[4]

...

因此,区间 [l,r] 的哈希值为  Hash(l,r) = Hash[r]-Hash[l-1]*P^{r-l+1}

我们看到哈希函数中存在指数级,所以一般都需要%MOD,我们一般取MOD=2^64,即用unsigned long long类型保存哈希值,让其自然溢出就好,因为此类型是不会出现负数的(无符号位)。

模版:

for(int i = 1; i <= n; ++i) hash[i] = hash[i - 1] * P + str[i] - 'a';  
inline ull getsub(int l, int r) {return hash[r] - hash[l - 1] * bin[r - l + 1];}  

bin[i]表示 P 的 i 次方,一般用O(n)打表而不用快速幂,因为多个log(n)可能会出事...

哈希须知:

两个元素若全等,其哈希值必定也相等;但哈希值相等,两个元素未必全等(哈希值相等是两个元素全等的必要不充分条件)。

即Hash时是尽量使冲突概率趋近于0,(尽量的满足其充分性),因此,脸黑的时候可能会同一个代码第一遍不过,第二遍过...

此外,字符串每种元素的值都要至少从1开始,不要从0开始。比如说小写字母,如果从0开始,即a=0,b=1,...,z=25,那么b和ab的哈希值会相同,这时候就会发生冲突,但从1开始就没这种问题了。

猜你喜欢

转载自blog.csdn.net/luyehao1/article/details/84930513