我正在学习字符串搜索算法,并了解它们的工作原理,但还没有找到足够好的答案来说明在哪些情况下Rabin-Karp算法比KMP或Boyer-Moore算法更有效。我看到它更容易实现,不需要同样的开销,但除此之外,我一无所知。
那么,在什么情况下使用Rabin-Karp比其他算法更好呢?
我正在学习字符串搜索算法,并了解它们的工作原理,但还没有找到足够好的答案来说明在哪些情况下Rabin-Karp算法比KMP或Boyer-Moore算法更有效。我看到它更容易实现,不需要同样的开销,但除此之外,我一无所知。
那么,在什么情况下使用Rabin-Karp比其他算法更好呢?
这些算法中有一些属性,在不同的情况下可能会使它们更具吸引力或不可取。以下是一个快速概述:
Rabin-Karp的一个主要优点是它使用O(1)辅助存储空间,这非常适合查找非常大的模式字符串。例如,如果您要在长度为109的长字符串中查找长度为107的字符串的所有出现,则不需要为故障函数或移位表分配107个机器字的表格就是一个主要的优势。Boyer-Moore和KMP在长度为n的模式字符串上都使用Ω(n)内存,因此在这里,Rabin-Karp将获胜。
Rabin-Karp存在两种潜在的最坏情况。首先,如果Rabin-Karp使用的特定质数已知于恶意攻击者,则该攻击者可能会创建一个输入,导致滚动哈希在每个时间点上匹配模式字符串的哈希值,从而导致算法的性能降至Ω((m - n + 1)n),其中m是字符串长度,n是模式长度。如果您正在接受不受信任的字符串作为输入,则可能存在潜在问题。Boyer-Moore和KMP都没有这些弱点。
a
的文本字符串中用Rabin-Karp算法查找一个由105个字母a
组成的字符串,那么模式字符串会出现许多次,每次都需要进行线性扫描。这也可能导致Ω((m + n - 1)n)的运行时间。假设您有一个固定的多个文本字符串集合需要搜索,而不仅仅是一个。如果您希望的话,可以跨这些字符串运行Rabin-Karp、KMP或Boyer-Moore的多个匹配过程以查找所有匹配项。然而,这种方法的运行时间并不好,它随要搜索的字符串数量呈线性增长。与此相反,KMP很好地推广到Aho-Corasick字符串匹配算法中,该算法在时间O(m + n + z)内运行,其中z是发现的匹配数,n是模式字符串的总长度。请注意,这里没有依赖于要搜索的不同模式字符串的数量!
Rabin-Karp 算法适用于查找多个模式匹配的大型文本,例如检测抄袭。
Boyer-Moore 算法适用于模式相对较大、字母表中等大小且词汇量较大的情况。但是它在处理二进制字符串或非常短的模式时效果不佳。
与此同时,KMP 算法适用于搜索较小的字母表,例如在生物信息学或二进制字符串中搜索。但如果字母表增加,它的执行速度将变慢。
所有三种算法的时间复杂度(供参考)
m:模式的长度
n:在其中搜索模式的字符串的长度
k:字母表的大小
拉宾-卡普算法:
O(1) 辅助空间
使用哈希来查找文本中模式字符串的完全匹配。它使用滚动哈希快速过滤掉无法与模式匹配的文本位置,然后检查剩余位置是否匹配。
Boyer-Moore算法:
最坏情况下性能:Θ(m) 预处理 + O(mn) 匹配
最佳情况下性能:Θ(m) 预处理 + Ω(n/m) 匹配
最坏空间复杂度:Θ(k)。
可用于类似“grep”的搜索。 https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm#Performance
Knuth Morris Pratt算法:
最坏情况下的性能:Θ(m) 预处理 + Θ(n) 匹配
最坏情况下的空间复杂度:Θ(m)
有关每个算法的更多详细信息,请在维基百科中查找。