字符串哈希 学习笔记
目录
- Part 1:什么是字符串哈希
- Part 2:字符串哈希(RK)算法的实现
- Part 3:练习
Part 1:什么是字符串哈希
所谓的字符串哈希,就是每个字符串都有一个 hash 值(如果字符串 s 和 t完全相等,那么它们的 hash 值也相等)。可以通过许多方法来求出字符串的 hash 值。
但是,许多方法求出的 hash 值可能不是很有效,即不同的字符串的 hash 值相等。因此,如果两个字符串的 hash 值不相同,则它们肯定不相同;如果它们的 hash 值相同,它们也不一定相同。
Part 2:字符串哈希(RK)算法的实现
RK 算法的思路:将模式串 p 的 hash 值跟主串 s 中的每一个长度为 |p| 的子串的 hash 值比较。如果不同,则它们肯定不相等;如果相同,则再逐位比较。
设模式串为 p,长度为 m;主串为 s,长度为 n。则模式串 p 可以看作是一个 m 位的 d 进制数 A,主串 s 可以看作是一个 n 位的 d 进制数。我们的模式匹配过程就是将 A 与主串中的每个长度为 m 的 d 进制数 S[t…t+m−1](t=0,1,2,…,n−m+1) 的值做比较,所以整个模式匹配过程就变成了两个 d 进制数之间的比较过程。例如模式串为 123,主串为 65127451234,就是将十进制数 123 跟十进制数 651,512,127,274,745,451,512,123 的逐个比较过程。
首先需要求解 A。根据上文可得:
A=Pm−1+d×(Pm−2+d×(Pm−3+⋯+d×(P1+d×P0)…))
我们可以发现,hash 值是可以递推转移的。因此,可以得出以下公式:
hash(t+1)=d×(hash(t)−dm−1×hash(t))+hash(t+m)
代码实现:
pair<int,int> hash_value(char s[],int len){
int u=0,v=0;
for(int i=0;i<len;++i){
u=(u*bas+s[i])%p1;
v=(v*bas+s[i])%p2;
}
return make_pair(u,v);
}//u和v分别代表这个字符串的两个hash值,这样更不容易出错
//注意数据范围,实际上int有点小