方法一:有限状态机
您可以将搜索词组合成一个有限状态机 (FSM)。然后,生成的 FSM 可以在线性时间内同时扫描文档中的所有术语。由于 FSM 可以在每个文档上重复使用,因此创建它的费用将分摊到您必须搜索的所有文本中。
一个好的正则表达式库会在幕后制作一个 FSM。编写代码来构建自己的代码可能超出了 Stack Overflow 答案的范围。
基本思想是从一个正则表达式开始,它是所有搜索词的交替。假设您的组织列表由“cat”和“dog”组成。您可以将它们组合为cat|dog。如果您还必须搜索“pink pigs”,您的正则表达式将是 cat|dog|pink pigs。
通过正则表达式,您可以构建图形。图表的节点是状态,用于跟踪您刚刚看到的文本。图的边是转换,告诉状态机在给定当前状态和输入中的下一个字符的情况下要进入哪个状态。某些状态被标记为“最终”状态,如果您到达其中之一,您就已经找到了您的组织之一的实例。
从除最琐碎的正则表达式之外的所有正则表达式构建图是乏味的,并且计算量可能很大,因此您可能希望找到一个已经完成这项工作的经过良好测试的正则表达式库。
方法 2:一次搜索一个词条
根据您有多少搜索词、有多少文档以及您的简单文本搜索工具的速度(可能是次线性的),最好只遍历这些词并在每个文档中搜索每个术语作为单独的命令。这当然是最简单的方法。
for doc in documents:
for term in search_terms:
search(term, doc)
请注意,以这种方式嵌套循环可能对磁盘缓存最友好。
如果这是一项一次性任务,我会采用这种方法。如果您必须不断搜索新文档(或使用不同的搜索词列表),这可能太昂贵了。
方法三:后缀树
将所有文档连接成一个巨大的文档,构建后缀树,对搜索词进行排序,然后遍历后缀树以查找匹配项。构建和使用后缀数组的大部分细节都在 Jon Bentley article from Dr. Dobb's 中,但您也可以找到许多其他资源。
这种方法是内存密集型的,主要是缓存友好的,因此非常快。