搜索文本中几个字符串之一的高效算法?

时间:2010-08-24 19:24:44

标签: c++ algorithm string-matching text-search

我需要搜索传入的非常长的文本片段以查找给定字符串的出现次数。字符串对于整个会话是不变的并且不是很多(~10)。另外的简化是没有任何字符串包含在任何其他字符串中。

我目前正在使用与str1 | str2 | ...匹配的boost正则表达式。这项任务的执行很重要,所以我想知道我是否可以改进它。并不是说我可以比推特人更好地编程,但也许专用的实现比普通实现更有效。

由于字符串长时间保持不变,我可以预先建立数据结构,如状态转换表。

例如,如果字符串是abcxbcycz,并且我到目前为止已阅读abc,那么我应处于合并状态,这意味着{ {1}}。然后阅读you're either 3 chars into string 1, 2 chars into string 2 or 1 char into string 1下一步会将我移至x州等,除string 1 matched以外的任何字符都将移至初始状态,我不需要缩回{{ 1}}。

感谢任何想法或参考。

8 个答案:

答案 0 :(得分:6)

答案 1 :(得分:4)

看看Suffix Tree

答案 2 :(得分:1)

我一直在寻找答案,但似乎都没有明确......而且大多数都归结为几个链接。

在这里引起我兴趣的是你的问题的独特性,到目前为止暴露的解决方案根本没有充分利用我们在大海捞针中同时寻找几个针的事实。

我肯定会看看KMP / Boyer Moore,但是我不会盲目地应用它们(至少如果你有时间在手上),因为它们是针对单针进行定制的,而且我很漂亮我们确信我们可以利用我们有几个字符串并使用自定义状态机(或BM的自定义表)同时检查所有字符串这一事实。

当然,它不太可能改善大O(Boyer Moore每个弦都以3n的速度运行,所以它无论如何都是线性的),但你可能会获得恒定因子。

答案 3 :(得分:1)

看看这个:http://www.boost.org/doc/libs/1_44_0/libs/regex/doc/html/boost_regex/configuration/algorithm.html

递归/非递归区分的存在是一个非常强烈的建议,即BOOST不一定是线性时间离散有限状态机。因此,你很有可能为你的特定问题做得更好。

最佳答案取决于您拥有多少干草堆和最小针数。如果最小针的长度超过几个字符,则可能比广义的正则表达式库更好一些。

基本上所有字符串搜索都是通过在当前位置(光标)测试匹配来工作的,如果没有找到,则再次尝试将光标向右滑动更远。

Rabin-Karp从您正在搜索的字符串(或字符串)中构建DFSM,以便在单个操作中组合测试和光标移动。然而,Rabin-Karp最初设计用于单针,因此如果一个匹配可能是另一个匹配的正确前缀,则需要支持回溯。 (请记住,当您想重用代码时。)

另一种策略是尽可能将光标向右滑动多个字符。 Boyer-Moore做到了这一点。它通常是针对单针制造的。构造一个包含所有字符的表格以及它们在针头中出现的最右侧位置(如果有的话)。现在,将光标定位在len(针)-1。表格条目将告诉您(a)从光标向左偏移可能找到针头,或者(b)您可以将光标len(针)向右移动更远。

当你有一个以上的针时,你的桌子的构造和使用变得更加复杂,但它仍然可能在探针上节省一个数量级。您仍然可能想要制作DFSM但不是调用常规搜索方法,而是调用do_this_DFSM_match_at_this_offset()。

另一种策略是一次测试超过8位。有一个垃圾邮件杀手工具,一次查看32位机器字。然后它执行一些简单的哈希代码以将结果拟合为12位,然后在表中查看是否存在命中。每个模式有四个条目(从模式的开始偏移0,1,2和3)然后这种方式尽管表中有数千个模式,但它们只测试主题中每个32位字的一个或两个线。

所以总的来说,是的,当针头不稳定时,你可以比正则表达式更快。<​​/ p>

答案 4 :(得分:0)

正则表达式引擎初始化预计会有一些开销, 所以,如果没有涉及真正的正则表达式, C - memcmp()应该没问题。

如果你能告诉文件大小并给出一些 具体用例,我们可以建立一个基准 (我认为这非常有趣)。

有趣:memcmp explorationstiming differences

此致

RBO

答案 5 :(得分:0)

始终有Boyer Moore

答案 6 :(得分:0)

除了Rabin-Karp算法和Knuth-Morris-Pratt算法之外,我的算法书为字符串匹配建议Finite State Machine。对于每个搜索字符串,您需要构建这样一个有限状态机。

答案 7 :(得分:0)

你可以用非常受欢迎的Lex&amp; Yacc工具,支持Flex和Bison工具。 您可以使用Lex获取字符串的标记。 将预定义的字符串与Lexer返回的标记进行比较。 找到匹配项后,执行所需操作。 有许多网站描述了Lex和Yacc。 其中一个网站是http://epaperpress.com/lexandyacc/