我试图在这里了解Rabin-Karp算法:http://algs4.cs.princeton.edu/53substring/RabinKarp.java.html。
我已经浏览了各种文章,现在我知道多项式散列的一般形式是C1 * A ^ k-1 + C2 * A ^ k-2 + C3 * A ^ k-3。查看代码,我了解它们如何在字符串中添加和减去数字。
txtHash = (txtHash + Q - RM*txt.charAt(i-M) % Q) % Q;
txtHash = (txtHash*R + txt.charAt(i)) % Q;
这里程序正在减去前导数字,乘以整个散列然后添加新数字。但是,当我查看计算哈希的函数时,它不遵循多项式哈希的一般形式。它看起来像这样:
private long hash(String key, int M) {
long h = 0;
for (int j = 0; j < M; j++)
h = (R * h + key.charAt(j)) % Q;
return h;
}
在这个函数中,它们将散列和基数相乘,然后添加key.charAt()。我想这个函数会将key.charAt()与一个从R ^ k-1开始的基数相乘。然后,当for循环继续时,基数将除以R以提供多项式中的递减幂。有人可以解释一下这个函数是如何工作的,它是如何以我上面提到的形式生成一个哈希的?谢谢!
答案 0 :(得分:0)
假设哈希函数需要传输3位数。 它看起来像是:
{digits[0]*R^2+digits[1]*R^1+digits[2]}%Q
= {(digit[0]*R^1+digits[1])*R+digits[2]}%Q
这会使哈希函数更容易计算。
然后适用于Rabin-Karp算法,
你可以看到
RM = R^2 %Q;(M=2)
当你想移动下一个数字进行验证时,
你需要删除最左边的数字并添加下一个数字。
txtHash = {[txtHash - R^2*most_left_digit(equal charAt(i-M))]*R+next_digit(equal charAt(i))}%Q
与
相同txtHash = (txtHash + Q - RM*txt.charAt(i-M) % Q) % Q;
txtHash = (txtHash*R + txt.charAt(i)) % Q;
Mod Q每个步骤都可以防止溢出。