【发布时间】:2010-12-18 10:41:01
【问题描述】:
我想要一个高效的算法(或库),我可以在 Java 中使用它来搜索字符串中的子字符串。
我想做的是:
给定一个输入字符串 - INSTR:
“BCDEFGH”
还有一组候选字符串——CAND:
“AB”、“CDE”、“FG”、“H”、“IJ”
在 INSTR
中查找任何与子字符串匹配的 CAND 字符串在本例中,我将匹配“CDE”、“FG”和“H”(但不匹配“AB”和“IJ”)
可能有数千个候选字符串(在 CAND 中),但更重要的是,我将进行数百万次此搜索,因此我需要它是 FAST。
我想使用 char 数组。此外,我对架构解决方案没有兴趣,例如分发搜索 - 只是在本地执行它的最有效的功能/算法。
此外,CAND 和 INSTR 中的所有字符串都相对较小(
更新我应该提到,CAND 字符串集在 INSTR 的所有值中是不变的。
更新我只需要知道有匹配 - 我不需要知道匹配是什么。
最终更新 由于实现简单,我选择尝试 AhoCorsick 和 Rabin-Karp。 因为我有可变长度的模式,所以我使用了一个修改过的 Rabin-Karp,它对每个模式的前 n 个字符进行哈希处理,其中 n 是最小模式的长度,N 是我的滚动子字符串搜索窗口的长度。 对于 Aho Corsick,我使用了 this
在我的测试中,我在两篇新闻报纸文章中搜索了 1000 种模式,平均经过 1000 次迭代等... 完成的标准化时间是:
AhoCorsick:1
拉宾卡普:1.8
朴素搜索(检查每个模式并使用 string.contains):50
*描述以下答案中提到的算法的一些资源:
http://www.seas.gwu.edu/~simhaweb/cs151/lectures/module5/module5.html
http://www.cs.princeton.edu/courses/archive/spr09/cos226/lectures/18SubstringSearch-2x2.pdf
【问题讨论】:
-
输入字符串相对于候选字符串有多长?
-
它们很短。输入字符串通常少于 40 个字符,候选字符串也是如此。
-
但可能有数千个候选字符串 - 我想在许多输入字符串中重复执行此操作数百万次。
-
鉴于细节,FSM 可能是您的最佳选择。
-
很好奇你期望的输出。是知道找到了一个就足够了,还是您需要知道找到了哪些?您是否需要知道每个子字符串被找到了多少次?
标签: java algorithm string search