Rabin-Karp:滚动哈希计算向先前计算的哈希添加一个大质数
Rabin-Karp: rolling hash computation adds a large prime number to previously computed hash
我想我在概念上理解了使用滚动哈希的 RabinKarp 模式匹配算法。在执行示例实现 here 时,我发现一个大素数 q
被添加到先前计算的滚动哈希中。
for (int i = m; i < n; i++) {
// Remove leading digit, add trailing digit, check for match.
txtHash = (txtHash + q - RM*txt.charAt(i-m) % q) % q; //Why +q here?
txtHash = (txtHash*R + txt.charAt(i)) % q;
// match
int offset = i - m + 1;
if ((patHash == txtHash) && check(txt, offset))
return offset;
}
我不确定为什么需要这样做。我可以得到一些帮助吗?
在我的有限测试中,无论是否包含 q
个术语,我都会得到相同的结果。
这是否与正在实施的算法版本 (Monte Carlo/Las Vegas) 有关?
+q
项用于避免处理负数。
我们希望txtHash
始终位于区间[0;q[
,没有这个+q
它也可能位于]-q;0[
.
这可能会导致丢失模式。例如,如果 patHash = 0xdead
但你计算 txtHash = -q+0xdead
。这两个值在数学上是相等的 mod q
但与 Java 不同 % q
.
我想我在概念上理解了使用滚动哈希的 RabinKarp 模式匹配算法。在执行示例实现 here 时,我发现一个大素数 q
被添加到先前计算的滚动哈希中。
for (int i = m; i < n; i++) {
// Remove leading digit, add trailing digit, check for match.
txtHash = (txtHash + q - RM*txt.charAt(i-m) % q) % q; //Why +q here?
txtHash = (txtHash*R + txt.charAt(i)) % q;
// match
int offset = i - m + 1;
if ((patHash == txtHash) && check(txt, offset))
return offset;
}
我不确定为什么需要这样做。我可以得到一些帮助吗?
在我的有限测试中,无论是否包含 q
个术语,我都会得到相同的结果。
这是否与正在实施的算法版本 (Monte Carlo/Las Vegas) 有关?
+q
项用于避免处理负数。
我们希望txtHash
始终位于区间[0;q[
,没有这个+q
它也可能位于]-q;0[
.
这可能会导致丢失模式。例如,如果 patHash = 0xdead
但你计算 txtHash = -q+0xdead
。这两个值在数学上是相等的 mod q
但与 Java 不同 % q
.