Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 搜索文本中多个字符串之一的有效算法?_C++_Algorithm_String Matching_Text Search - Fatal编程技术网

C++ 搜索文本中多个字符串之一的有效算法?

C++ 搜索文本中多个字符串之一的有效算法?,c++,algorithm,string-matching,text-search,C++,Algorithm,String Matching,Text Search,我需要搜索传入的不太长的文本片段以查找给定字符串的出现。字符串在整个会话中都是常量,并且不多(~10)。额外的简化是,任何其他字符串中都不包含任何字符串 我目前正在使用boost正则表达式与str1 | str2 |…进行匹配。这项任务的表现很重要,所以我想知道我是否能改进它。并不是说我的编程能力比boost强,但也许专用的实现比一般的实现更有效 由于字符串在很长一段时间内保持不变,我可以预先构建数据结构,如状态转换表 e、 例如,如果字符串是abcx、bcy和cz,并且我已经读过abc,我应该

我需要搜索传入的不太长的文本片段以查找给定字符串的出现。字符串在整个会话中都是常量,并且不多(~10)。额外的简化是,任何其他字符串中都不包含任何字符串

我目前正在使用boost正则表达式与
str1 | str2 |…
进行匹配。这项任务的表现很重要,所以我想知道我是否能改进它。并不是说我的编程能力比boost强,但也许专用的实现比一般的实现更有效

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

e、 例如,如果字符串是
abcx
bcy
cz
,并且我已经读过
abc
,我应该处于组合状态,这意味着
您要么将3个字符放入字符串1,要么将2个字符放入字符串2,要么将1个字符放入字符串1
。然后读取
x
next将把我移到
string1 matched
状态等,除
xyz
以外的任何字符都将移到初始状态,我不需要缩回
b


欢迎提供任何想法或参考。

正则表达式引擎初始化预计会有一些开销, 因此,如果不涉及正则表达式, C-memcmp()应该可以

如果你能说出文件大小并给出一些 在特定的用例中,我们可以构建一个基准 (我认为这很有趣) 有趣的是:和

问候


rbo

看看。

除了Rabin-Karp算法和Knuth-Morris-Pratt算法之外,我的算法书还建议使用一种字符串匹配算法。对于构建这样一个有限状态机所需的每个搜索字符串。

请查看

我一直在看答案,但没有一个答案是明确的。。。主要归结为几个链接

这里让我感兴趣的是你的问题的独特性,迄今为止暴露的解决方案根本没有利用我们正在大海捞针的事实

我当然会看看KMP/Boyer-Moore,但我不会盲目地应用它们(至少如果你手头有时间的话),因为它们是为一根针量身定做的,我非常相信我们可以利用我们有几个字符串的事实,使用自定义状态机一次检查所有字符串(或BM的自定义表)

当然,这不太可能改善大O(Boyer Moore以3n表示每根字符串,因此它无论如何都是线性的),但您可能会获得常数因子。

看看这个:

递归/非递归区别的存在是一个非常有力的证据,表明BOOST不一定是一个线性时间离散有限状态机。因此,你很有可能对你的特定问题做得更好

最好的答案在很大程度上取决于你有多少干草堆和一根针的最小尺寸。如果最小的针长于几个字符,你可能比一般的正则表达式库做得更好

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

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

另一种策略是尽可能将光标向右滑动一个以上的字符。Boyer Moore会这样做。它通常是为一根针构建的。构建一个包含所有字符及其在针中出现的最右侧位置(如果有)的表格。现在,将光标定位在len(Pineer)-1。表格条目将告诉您(a)从光标向左偏移多少,可以找到指针,或者(b)可以将光标len(指针)进一步向右移动

当您有多个指针时,表的构造和使用会变得更加复杂,但它仍可能为您节省一个数量级的探针。您可能仍希望创建DFSM,但不是调用常规搜索方法,而是调用does_this_DFSM_match_at_this_offset()

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


因此,一般来说,是的,当指针不变时,您可以比正则表达式运行得更快。

您可以使用非常流行的Lex和Yacc工具,并支持Flex和Bison工具。 可以使用Lex获取字符串的标记。 将预定义字符串与Lexer返回的标记进行比较。 找到匹配项后,执行所需操作。 有许多网站描述了Lex和Yacc。
一个这样的网站是

你在使用预编译的正则表达式对象吗?我不知道boost:但是大多数使用正则表达式的语言。使用正则表达式来构建一个用于解析文本的有限状态机的等价物,因此非常有效。请发布你正在使用的正则表达式。可能还有改进的余地nt那里。@John Dibling:如前所述,我只是用OR运算符连接字符串:
str1 | str2 |……
as@maxschlepzig-sug