在顶级编码器的RK算法代码中:
// correctly calculates a mod b even if a < 0
function int_mod(int a, int b)
{
return (a % b + b) % b;
}
function Rabin_Karp(text[], pattern[])
{
// let n be the size of the text, m the size of the
// pattern, B - the base of the numeral system,
// and M - a big enough prime number
if(n < m) return; // no match is possible
// calculate the hash value of the pattern
hp = 0;
for(i = 0; i < m; i++)
hp = int_mod(hp * B + pattern[i], M);
// calculate the hash value of the first segment
// of the text of length m
ht = 0;
for(i = 0; i < m; i++)
ht = int_mod(ht * B + text[i], M);
if(ht == hp) check character by character if the first
segment of the text matches the pattern;
// start the "rolling hash" - for every next character in
// the text calculate the hash value of the new segment
// of length m; E = (Bm-1) modulo M
for(i = m; i < n; i++) {
ht = int_mod(ht - int_mod(text[i - m] * E, M), M);
ht = int_mod(ht * B, M);
ht = int_mod(ht + text[i], M);
if(ht == hp) check character by character if the
current segment of the text matches
the pattern;
}
}
写的是
不幸的是,仍有一些情况我们必须为文本中的每个起始位置运行“天真”方法的整个内循环 - 例如,在字符串“aaaaaaaaaaaaaaaaaaaaaaa”中搜索模式“aaa”时 - 所以在最坏的情况下,我们仍然需要(n * m)次迭代。
但是,算法不会在第一次迭代时停止 - 就像它会看到前三个字母是&#39; a&#39;哪个与针匹配?
答案 0 :(得分:1)
假设我们要搜索的字符串不是&#34; aaa&#34;而是一些其他字符串,其散列与&#34; aaa&#34;的散列相同。然后,每个点都需要进行比较。
当然,我们希望比较早于m
个字符失败,但可能需要o(m)个字符。
话虽如此,RK的一个常见用途是找到所有(重叠)实例,在这种情况下引用的例子显然是o(mn)。
答案 1 :(得分:1)
Rabin-Karp算法保持计算大小为text
的{{1}}的所有子字符串的哈希值,并将其与M
的哈希值匹配。现在,可以有多个子字符串具有相同的哈希值。
因此,当pattern
的哈希值和pattern
的某些子字符串匹配时,我们需要再次迭代它们,以确保它们实际上是否相同。
如果是text
和pattern = "AAA"
,则有text = "AAAAAAAAAAAAA"
个子字符串与O(n)
的哈希值匹配。对于每场比赛,我们需要在pattern
时间内进行迭代确认;因此最坏情况的复杂性O(m)
。