【发布时间】:2019-10-18 12:02:30
【问题描述】:
我正在学习字符串搜索算法并了解它们的工作原理,但还没有找到足够好的答案来说明在哪些情况下 Rabin-Karp 算法会比 KMP 或 Boyer-Moore 更有效。我发现它更容易实现并且不需要相同的开销,但除此之外,我不知道。
那么,Rabin-Karp 什么时候比其他方法更好用?
【问题讨论】:
标签: string-search knuth-morris-pratt rabin-karp boyer-moore
我正在学习字符串搜索算法并了解它们的工作原理,但还没有找到足够好的答案来说明在哪些情况下 Rabin-Karp 算法会比 KMP 或 Boyer-Moore 更有效。我发现它更容易实现并且不需要相同的开销,但除此之外,我不知道。
那么,Rabin-Karp 什么时候比其他方法更好用?
【问题讨论】:
标签: string-search knuth-morris-pratt rabin-karp boyer-moore
这些算法中的每一个都具有一些属性,这些属性可能使它们在不同的情况下成为可取或不可取的。以下是简要介绍:
Rabin-Karp 的一个主要优点是它使用 O(1) 辅助存储空间,如果您要查找的模式字符串非常大,这将非常有用。例如,如果您要在长度为 109 的较长字符串中查找长度为 107 的字符串的所有匹配项,则不必分配 107 用于故障函数或移位表的机器词是一个重大胜利。 Boyer-Moore 和 KMP 都在长度为 n 的模式字符串上使用 Ω(n) 内存,因此 Rabin-Karp 在这里将是一个明显的胜利。
Rabin-Karp 有两种潜在的最坏情况。首先,如果恶意对手知道 Rabin-Karp 使用的特定素数,那么该对手可能会制作一个输入,使滚动散列在每个时间点与模式字符串的散列相匹配,从而导致算法的性能下降。在长度为 m 的字符串和长度为 n 的模式上降级为 Ω((m - n + 1)n)。如果您将不受信任的字符串作为输入,这可能是一个问题。 Boyer-Moore 和 KMP 都没有这些弱点。
类似地,如果您想在该模式多次出现的情况下查找模式字符串的所有匹配项,Rabin-Karp 会很慢。例如,如果您要在由字母 a 的 109 个副本组成的文本字符串中查找字母 a 的 105 个副本的字符串Rabin-Karp,那么会有很多点出现模式串,每个点都需要线性扫描。这也可能导致 Ω((m + n - 1)n) 的运行时间。
许多 Boyer-Moore 实现都受到第二条规则的影响,但在第一种情况下不会有糟糕的运行时。而且 KMP 没有像这样的病态最坏情况。
Boyer-Moore 算法的一个优点是它不必扫描输入字符串的所有字符。具体来说,坏字符规则可用于在不匹配的情况下跳过输入字符串的大块区域。更具体地说,Boyer-Moore 的最佳运行时间是 O(m / n),这比 Rabin-Karp 或 KMP 所能提供的要快得多。
假设您要搜索一组固定的多个文本字符串,而不仅仅是一个。如果您愿意,您可以在字符串上运行多次 Rabin-Karp、KMP 或 Boyer-Moore 以查找所有匹配项。但是,这种方法的运行时间不是很好,因为它与要搜索的字符串的数量呈线性关系。另一方面,KMP 很好地推广到 Aho-Corasick 字符串匹配算法,该算法在 O(m + n + z) 时间内运行,其中 z 是找到的匹配数,n 是模式字符串的组合长度。请注意,这里不依赖于正在搜索的不同模式字符串的数量!
【讨论】:
Rabin-Karp 算法在搜索查找多个模式匹配的大文本时效果更好,例如检测抄袭。
而 Boyer-Moore 在模式相对较大且字母大小适中且词汇量较大的情况下效果更好。而且它不适用于二进制字符串或非常短的模式。
同时,KMP 适合在较小的字母表中搜索,例如在生物信息学中或在二进制字符串中搜索。如果字母增加,它也不会跑得很快。
【讨论】:
三者的时空复杂性(供参考) (用于查找所有出现的模式)
m : 模式的长度
n : 我们在其中搜索模式的字符串的长度
k : 字母的大小
拉宾·卡普:
O(1) 个辅助空间
使用散列来查找文本中模式字符串的完全匹配。它使用滚动散列快速过滤掉与模式不匹配的文本位置,然后检查剩余位置是否匹配
博耶摩尔:
最坏情况下的性能:Θ(m) 预处理 + O(mn) 匹配
最佳情况性能:Θ(m) 预处理 + Ω(n/m) 匹配
最坏情况空间复杂度:Θ(k)。
可用于类似“grep”的搜索。 https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm#Performance
克努斯·莫里斯·普拉特:
最坏情况下的性能:Θ(m) 预处理 + Θ(n) 匹配
最坏情况空间复杂度:Θ(m)
有关每种算法的更多详细信息,请在 Wikipedia 中查找。
【讨论】: