概述
字符串哈希全称字符串前缀哈希法,把字符串映射为一个P进制数,实现不同的字符串映射不同的数字
注意
字符不能映射为0,不然会导致冲突,例如A,AA都为0
P取131或13331的冲突概率低
计算结果可能会溢出,需要取模,用2^64,这样用unsigned long long存储,溢出的结果就是取模的结果
例子
以十进制为例,P=10,假设字符只包含1~9且权值为1 ~ 9
维护字符串的哈希值:对于字符串“123”,h[1]=1,h[2]=12,h[3]=123,即用前面的哈希值乘以进制加上当前权值
判断字符串是否相同:假设给定字符串a="59123"和字符串b=“123”,问a中的"123"和b中的"123"是否为同一个字符串。通过维护两个字符串的哈希值得到a字符串的h[5]=59123,b字符串的h[3]=123,现在要把a中"123"的哈希值取出来,如果用"123"之前"59"的哈希值乘以一定的值,使其与59123的位数一样,就可以用59123减去,求出123。乘以多少呢?看相差的位数,是所求字符串的长度,如"59"和"59123"相差的位数是3,即"123"的长度,因此是p[3]=1000,59123-59*1000=123,同样求出b中“123”的哈希值,两者相等,字符串相同
代码
typedef unsigned long long ull;
ull h[N],p[N];//h[i]为前i个字符的哈希值,p[i]为P^i
//初始化
p[0]=1;
for(int i=1;i<=n;++i)
{
h[i]=h[i-1]*P+s[i];
p[i]=p[i-1]*P;
}
//获取s[l~r]的哈希值
ull get(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}