使用Rabin-Karp在字符串中搜索多个模式

时间:2009-08-23 09:10:12

标签: algorithm hash language-agnostic string-matching rabin-karp

根据关于Rabin-Karp字符串匹配算法的wikipedia entry,它可以用于同时在字符串中查找几种不同的模式,同时仍保持线性复杂性。很明显,当所有模式具有相同的长度时,这很容易完成,但是当我同时搜索具有不同长度的模式时,我仍然不知道如何保持O(n)复杂度。有人可以对此有所了解吗?

编辑(2011年12月):

维基百科文章已经更新,不再声称匹配O(n)中不同长度的多种模式。

2 个答案:

答案 0 :(得分:5)

我不确定这是否是正确答案,但无论如何:

在构造哈希值时,我们可以检查字符串哈希值中的匹配项。 Aka,当前哈希值。散列函数/代码通常实现为循环,在循环内部我们可以插入快速查找。

当然,我们必须选择m以获得字符串集中的最大字符串长度。

更新:来自维基百科,

[...]
for i from 1 to n-m+1
         if hs ∈ hsubs
             if s[i..i+m-1] = a substring with hash hs
                 return i
         hs := hash(s[i+1..i+m]) // <---- calculating current hash
[...]

我们在m步骤中计算当前哈希值。在每一步中都有一个临时哈希值,我们可以在哈希集中查找(O(1)复杂度)。所有散列都具有相同的大小,即32位。

更新2:摊销(平均)O(n)时间复杂度?

上面我说m必须有最大字符串长度。事实证明,我们可以利用相反的情况 使用hashing for shifting substring search和固定m大小,我们可以实现O(n)复杂度。

如果我们有可变长度字符串,我们可以将m设置为最小字符串长度。另外,在散列集合中,我们不会将散列与整个字符串相关联,而是将其与第一个m字符相关联 现在,在搜索文本时,我们检查当前哈希是否在哈希集中,并检查匹配的关联字符串。

这种技术会增加误报,但平均而言,它具有O(n)时间复杂度。

答案 1 :(得分:0)

这是因为子串的哈希值在数学上是相关的。计算散列 H(S,j)(从字符串 S 的第j个位置开始的字符的散列)需要 O(m)时间长度为 m 的字符串。但是一旦你有了,计算 H(S,j + 1)就可以在恒定时间内完成,因为 H(S,j + 1)可以表示为 H(S,j)的功能。

O(m)+ O(1)=&gt; O(m),即线性时间。

Here's a link这里有更详细的描述(参见例如“什么使Rabin-Karp禁食?”)