何时使用 Rabin-Karp 或 KMP 算法?

Posted

技术标签:

【中文标题】何时使用 Rabin-Karp 或 KMP 算法?【英文标题】:When to use Rabin-Karp or KMP algorithms? 【发布时间】:2014-04-28 09:03:15 【问题描述】:

我使用以下字母生成了一个字符串。 A,C,G,T。我的字符串包含超过 10000 个字符。我正在其中搜索以下模式。

ATGGA TGGAC CCGT

我要求使用具有O(m+n) 运行时间的字符串匹配算法。

m = pattern length
n = text length

KMP and Rabin-Karp algorithms 都有这个运行时间。在这种情况下,最合适的算法是什么(在 Rabin-Carp 和 KMP 之间)?

【问题讨论】:

如果您已经为其中一个或两个实现了一些代码,您可能还想在 codereview.stackexchange.com 中发布此代码 感谢您的快速回复。我已经发展到生成字符串。我想验证要使用的算法是什么。只有我才能继续开发 Rabin-Karp 是O(n*m)(最坏情况)。 你想过阿霍-科拉西克吗?它非常接近您对O(m+n) 的要求,是匹配多种模式的好选择,并且易于并行化。 @Michael Foukarakis:感谢您的建议。但我只想在这两者之间选择一种算法。 【参考方案1】:

当您要搜索多个模式时,通常正确的选择是使用Aho-Corasick,这在某种程度上是KMP 的概括。现在,在您的情况下,您只搜索 3 种模式,因此 KMP 可能并没有那么慢(最多 3 次),但这是一般方法。

Rabin-Karp 如果我们假设永远不会发生冲突,则更容易实现,但如果您遇到的问题是典型的字符串搜索,则无论您有什么输入,KMP 都会更加稳定。但是,Rabin-Karp 有许多其他应用程序,其中 KMP 不是一个选项。

【讨论】:

在这种特殊情况下,您的字符串非常小,因此您可以计算完美的哈希值,避免冲突(对算法稍作修改)。因此,我认为这两种方法都行得通。如果搜索模式可以变得更长,这是不可能的。我的回答旨在解释类似问题的一般逻辑。对于这个问题,我认为这两种方法都一样好。也许您可以对这两种解决方案进行基准测试并选择性能更好的一种? 谢谢。 “但是 Rabin-Karp 有许多其他应用程序,其中 KMP 不是一个选项”中的应用程序是什么? “典型的字符串搜索 KMP 会更稳定”中的稳定是什么意思? @Tim Rabin Karp 取决于散列函数的选择,无论您选择什么函数,都会出现由于冲突而导致性能下降的情况。 KMP 没有这个缺点,这就是我所说的“更稳定”的意思(也许这个短语不是最适合在这种情况下使用)。我用 Rabin-Karp 解决了许多不同的问题,但这里有一些其他应用:它可以用来解决最大子回文问题(也有其他方法),我用它来找到重复的最长子字符串生成给定的输入字符串。 @IvayloStrandjev 或任何人都可以提供 Rabin Karp 完全适合的场景/问题? 我用它解决了许多不同的问题。例如,使用 rabin-karp 您可以计算 O(n*log(n)) 中最长的回文子串(结合两个 rabin karp 用于两个方向和二分搜索)。

以上是关于何时使用 Rabin-Karp 或 KMP 算法?的主要内容,如果未能解决你的问题,请参考以下文章

Implement strStr() LeetCode Java

字符串字符串查找 ( Rabin-Karp 算法 )

Rabin-Karp 字符串搜索算法

PHP 中的 Rabin-Karp 算法

C# 中的 Rabin-Karp 算法 [关闭]

Rabin-Karp算法代码中的负哈希值