用于搜索字符串中子字符串的快速算法

2022-09-01 11:45:22

我想要一个有效的算法(或库),我可以在Java中使用它来搜索字符串中的子字符串。

我想做的是:

给定一个输入字符串 - INSTR

“BCDEFGH”

和一组候选字符串 - CAND

“AB”, “CDE”, “FG”, “H”, “IJ”

查找在 INSTR 中作为子字符串匹配的任何 CAND 字符串

在这个例子中,我会匹配“CDE”,“FG”和“H”(但不是“AB”和“IJ”)

可能有数千个候选字符串(在CAND中),但更重要的是,我将进行数百万次搜索,因此我需要它快速。

我想使用 char 数组。此外,我没有在架构解决方案方面进行测试,比如分发搜索 - 只是在本地执行此操作的最有效函数/算法。

此外,CAND和INSTR中的所有字符串都将相对较小(<50个字符) - 即目标字符串INSTR相对于候选字符串不长。


更新我应该提到,CAND字符串的集合在INSTR的所有值中都是不变的。

更新我只需要知道有一场比赛 - 我不需要知道比赛是什么。

最终更新我选择尝试AhoCorsick和Rabin-Karp,因为实施简单。因为我有可变长度的模式,所以我使用了一个修改的Rabin-Karp,它对每个模式的前n个字符进行哈希处理,其中n是最小模式的长度,N是滚动子字符串搜索窗口的长度。对于Aho Corsick,我用了这个

在我的测试中,我在两篇文档新闻论文文章中搜索了1000种模式,平均在1000次迭代中以此类推......标准化的完成时间为:

阿霍科西克: 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

http://www-igm.univ-mlv.fr/~lecroq/string/index.html*


答案 2

将候选字符串集转换为确定性有限状态自动机,然后在线性时间内运行输入字符串。将单个字符串转换为 DFS 在标准书籍中有很好的介绍。您可以通过首先构造非确定性自动机,然后确定它来转换一组字符串。在最坏的情况下,自动机的大小可能会产生指数级爆炸,但之后的搜索速度很快;特别是如果目标字符串很长,而候选者很短,这将很好地工作。