我正在使用C#在大字符串中连续搜索多个字符串“关键字”,其中> = 4kb。这段代码不断循环,睡眠不会在保持合理速度的同时降低CPU使用率。 bog-down是关键字匹配方法。
我发现了一些可能性,并且它们都具有相似的效率。
1)http://tomasp.net/articles/ahocorasick.aspx - 我没有足够的关键字来成为最有效的算法。
2)正则表达式。使用实例级别,编译正则表达式。 - 提供比我要求更多的功能,效率不够。
3)String.IndexOf。 - 我需要做一个“智能”版本,因为它提供了足够的效率。循环遍历每个关键字并调用IndexOf不会削减它。
有没有人知道我可以用来实现目标的任何算法或方法?
答案 0 :(得分:3)
我没试过,但你看过Rabin-Karp了吗?显然它具有糟糕的最坏情况复杂性,但通常非常好。
您的关键字是什么样的?特别是,它们总是被空格(或类似的东西)界定吗?如果是这样,你可以在查找“单词”后查看字符串,然后创建从单词到该单词索引列表的映射,或者只对你感兴趣的关键字进行映射。
如果您可以提供更多有关确切情况的详细信息(例如关键字,分隔符以及搜索结果所需的内容),那将会有所帮助。
答案 1 :(得分:3)
您是否一直在寻找相同的关键字? 试试Boyer-Moore。它需要对关键字进行一些预处理,但之后会加快速度。
答案 2 :(得分:2)
我为这个问题开发了IndexOf的有效使用:
A better way to replace many strings - obfuscation in C#
它使用关键字列表及其在字符串中的下一个位置。这样,您只需为每个关键字调用一次IndexOf,然后为您找到的每个匹配调用一次。替换大字符串中的关键字时效率特别高,因为您可以从头到尾处理字符串,而不是为每个关键字处理整个字符串一次。我不知道你为什么要在字符串中查找关键字以及你对字符串做什么,但也许它可能对你的情况有用。
答案 3 :(得分:2)
其实我以前必须解决这个问题,这很有趣。我有20k个html页面,每个页面都有一个标题,并希望其他页面上所有其他标题都链接到带有该标题的页面。听起来与你想要完成的事情非常相似。
方法:
听起来比实际情况复杂,需要两天时间才能让它运转良好。
然而,你解决它,玩得开心:)
答案 4 :(得分:0)
我刚刚在类似的帖子上发布了这个帖子,但这里可能更相关。
我正在进行类似的搜索,基本上在大约45k字节的文本中寻找大约10-50字节长的关键字。我在900万个文本中搜索了大约1900个关键词,因此尽可能快地获得这个关键词也是一个类似的优先事项。
因此,我发现使用.NET 4的最快方法是并行Regex IsMatch。
以下是获得总匹配的示例 -
needles.AsParallel ( ).Sum ( l => Regex.IsMatch ( haystack , Regex.Escape ( l ) ) ? 1 : 0 );
这适用于我的场景(上图),比我的测试中的并行比较快55%,至少对于我使用的数据大小。我还想象只有在使用多核机器时才会出现速度提升。
如果有人能找到更快的方法,会有兴趣吗?