我有一个单词列表,相当小的约1000左右。我想检查该列表中的任何单词是否出现在输入文本中。如果是这样,我想知道发生了哪些。输入文本每个都是几百个单词,这些是来自网络的文本段落 - 这意味着很多来自不同的网站。我正在努力为它找到最好的算法。
我可以看到两种明显的方法 -
从文本列表中搜索每个单词的强力方式。
从输入文本创建单词的哈希表,然后从哈希表中的列表中搜索每个单词。这很快。
有更好的解决方案吗?
我正在使用python虽然我不确定是否会改变算法。
同样作为上述解决方案2的优化,我想将生成的哈希表存储到持久存储(DB),这样如果单词列表发生更改,我可以重新使用哈希表而不必再次创建它。当然如果输入文本改变,我必须生成哈希表。是否可以将哈希表保存到数据库?有什么建议?我目前正在为我的项目使用MongoDB,我只能在其中存储json文档。我是MongoDB的新手,刚刚开始使用它,但仍然没有完全理解它的全部潜力。
我搜索了SO并看到了两个类似的问题,其中一个问题提出了一个哈希表,但我希望得到任何关于我想到的优化的指示。
以下是关于SO的先前问题 -
Is there an efficient algorithm to perform inverted full text search?
Searching a large list of words in another large list
编辑:我刚刚在SO上发现了另一个关于同样问题的问题。Algorithm for multiple word matching in text
我猜没有比哈希表更好的解决方案了。但我真的想优化它,以便对单词列表的更改可以让我在快速存储的所有文本上运行算法。我应该更改添加到问题中的标签还包括一些数据库技术吗?
答案 0 :(得分:7)
是一个比哈希表更好的解决方案。如果您要在大量文本中搜索一组固定的单词,则使用Aho-Corasick string matching algorithm进行搜索。
该算法根据您要搜索的单词构建状态机,然后通过该状态机运行输入文本,在找到匹配项时输出匹配项。因为构建状态机需要一些时间,所以该算法最适合搜索非常大的文本体。
您可以使用正则表达式执行类似操作。例如,您可能希望在某些文本中找到“dog”,“cat”,“horse”和“skunk”等字样。您可以构建正则表达式:
"dog|cat|horse|skunk"
然后在文本上运行正则表达式匹配。如何获得所有匹配将取决于您的特定正则表达式库,但它确实有效。对于非常大的单词列表,你需要编写读取单词并生成正则表达式的代码,但这并不是非常困难,而且效果非常好。
然而,正则表达式的结果和Aho-Corasick算法的结果存在差异。例如,如果你在字符串“我的业力吃了你的教条”中搜索“dog”和“dogma”这两个词。正则表达式库搜索将报告发现“教条”。 Aho-Corasick实施将报告在同一位置发现“狗”和“教条”。
如果您希望Aho-Corasick算法仅报告整个单词,则必须稍微修改算法。
正则表达式也将报告部分单词的匹配。也就是说,如果你正在寻找“狗”,它会在“教条”中找到它。但是你可以修改正则表达式只给出整个单词。通常,这是使用\b
完成的,如:
"\b(cat|dog|horse|skunk)\b"
您选择的算法很大程度上取决于输入文本的大小。如果输入文本不是太大,您可以创建您要查找的单词的哈希表。然后浏览输入文本,将其分解为单词,并检查哈希表以查看该单词是否在表中。在伪代码中:
hashTable = Build hash table from target words
for each word in input text
if word in hashTable then
output word
或者,如果您想要输入文本中匹配单词的列表:
hashTable = Build hash table from target words
foundWords = empty hash table
for each word in input text
if word in hashTable then
add word to foundWords