【发布时间】:2022-01-18 01:05:26
【问题描述】:
我有这个 Rabin Karp 实现。现在我对滚动哈希所做的唯一事情就是从sourceHash 中减去power*source[i]。 power 是 31^target.size()-1 % mod
但我不明白为什么当它变成负数时我们将mod 添加到sourceHash。我尝试添加其他值,但它不起作用,并且仅在我们添加 mod 时才起作用。为什么是这样?我们添加 mod 而不是其他任何内容(例如随机大数字)是否有特定原因。
int rbk(string source, string target){
int m = target.size();
int n = source.size();
int mod = 128;
int prime = 11;
int power = 1;
int targetHash = 0, sourceHash = 0;
for(int i = 0; i < m - 1; i++){
power =(power*prime) % mod;
}
for(int i = 0; i < target.size(); i++){
sourceHash = (sourceHash*prime + source[i]) % mod;
targetHash = (targetHash*prime + target[i]) % mod;
}
for(int i = 0; i < n-m+1; i++){
if(targetHash == sourceHash){
bool flag = true;
for(int j = 0; j < m; j++){
if(source[i+j] != target[j]){
flag = false;
break;
}
}
if(flag){
return 1;
}
}
if(i < n-m){
sourceHash = (prime*(sourceHash - source[i]*power) + source[i+m]) % mod;
if(sourceHash < 0){
sourceHash += mod;
}
}
}
return -1;
}
【问题讨论】:
-
确保它在区间 [0, mod) 内。
-
是不是因为你应该使用无符号类型但使用的是有符号类型?
-
@MadPhysicist 我试过只是翻转标志,但结果是错误的答案。
-
没有。基本思想是将无限空间映射到有限空间。 mod 做得很好,因为无论输入数字如何,它都会循环回到区间。另一方面,如果你使用一个大常数,总有一些数字加到这个大数字上会落在可用有限空间之外。
-
@user1984 这仍然让我感到困惑,因为即使我们以某种方式使 sourceHash 为正,即使在 0 到 mod 的范围内,其他值仍然不能给我们一个好的答案.我尝试过尽可能接近 mod 值的数字,但我只是不明白为什么只有 mod 有效。在某些情况下修改sourceHash不应该以某种方式产生不一致吗?
标签: c++ algorithm rabin-karp