一般和python中执行字符串搜索的最快方法

时间:2012-10-28 04:36:33

标签: python algorithm search complexity-theory

我的任务是在非常短的文档列表中搜索字符串或模式(比如200个字符长)。但是,据说这个时间有100万份文件。执行此搜索的最有效方法是什么?我正在考虑对每个文档进行标记,并将单词作为键和文档编号作为值放在哈希表中,然后创建一个单词。然后执行单词搜索并检索包含该单词的文档列表。从我所看到的是这个操作将采取O(n)操作。还有其他方法吗?可能没有使用哈希表?。

此外,是否有可以执行高效搜索的python库或第三方软件包?

4 个答案:

答案 0 :(得分:4)

由于您正在寻找一个库,您是否看过PyLucene?

http://lucene.apache.org/pylucene/features.html

虽然Lucene通常实施排名检索(基于相对分数的匹配) - 而不是精确匹配 - 但它可以用于精确短语搜索。这是一个如何使用Lucene搜索确切短语的链接。它是用Java编写的,但提出了这个想法:

Exact Phrase search using Lucene?

您的问题专门针对效率问题。效率以什么方式?我认为你的意思是给用户最快的查找时间。如果您确实在谈论速度纯粹就用户的查找时间而言,那么没有比实际索引文档中的所有单词更快的方式,前提是您愿意忍受索引语料库中所有文档的初始时间。这通常是合乎逻辑的选择,因为索引是一次性事件,并且用户搜索经常发生。但显然,这需要相当大的内存使用量。因此,如果您在谈论内存使用方面的效率,那么您可能希望遍历所有文档并对每个文档执行正则表达式搜索。如果你想避免索引的初始查找时间,你也可以使用这种方法,但是,考虑到大的语料库大小,这不太可能是逻辑限制因素,并且考虑到关注通常是满足将要制作的用户多个查询。

我要指出的唯一另一件事是,既然你提到你正在搜索模式而不仅仅是单词,那么如果你试图支持查询模式,那么索引只有单词将无济于事(除非该模式是文档中的一个词!)

如果你不打算使用Lucene,而是想自己实现这个,请看一下使用倒置的indeces进行索引。如果您正在寻找短语查询,这里有一个很好的解释如何创建倒排索引:

http://www.searchenginepeople.com/blog/how-search-really-works-the-index-2.html

答案 1 :(得分:3)

大多数搜索引擎都是按倒排索引的原则工作的。基本上对于每个标记(单词,三元组等),您存储包含此标记的已排序文档列表。匹配查询时,合并连接所有必需标记的列表以生成候选文档列表。如果索引匹配不保证查询匹配,则必须在匹配的文档上重新测试查询表达式。

有许多解决方案来存储倒排索引,其中一些已经(Lucene,Sphinx,PostgreSQL FTS)支持在倒排索引上计算表达式。

搜索引擎的神奇之处主要在于对文档进行预处理和标记,并根据用户请求生成搜索查询。预处理技巧包括通过词干化和每个单词存储多个不同表示来进行单词规范化。对于查询构造,您可能希望执行同义词替换等操作。正则表达式有点棘手,但有关implementing index support for regular expression searches in PostgreSQL的讨论很棒。

答案 2 :(得分:1)

虽然你的想法使用哈希表来制作单词听起来很有趣,但我认为当你打开每个文件时,将其读入内存,对其进行标记,制作哈希表,将每个标记放入哈希表,哈希搜索词,然后索引到您的哈希表中以查找包含该单词的每个文档的文档ID,您花费的时间远远超过使用正则表达式并在每个文件中搜索时所花费的时间:

import re
import os
import sys

searchterm = sys.argv[1]
searchexp = re.compile("(%s)" % searchterm, re.M)

for filename in os.listdir(sys.argv[2]):
    f = open(os.path.join(sys.argv[2], filename), 'r')
    contents = f.read()
    f.close()
    if searchexp.search(contents):
        print(filename)

那太慢了吗?

答案 3 :(得分:1)

我认为这个问题没有比Russ Cox描述的here更好的解决方案,他为悲惨的退役Google代码搜索引擎开发了这个问题。