帮我优化我的索引字符串搜索

时间:2011-02-24 18:23:34

标签: algorithm string optimization search indexing

因此,作为练习,我正在构建一种算法,以便尽可能快地在较大的字符串中搜索单词(任意字符集)。由于几乎没有现有搜索算法的先前知识,到目前为止,我的方法如下:

  1. 映射出较大字符串中出现的字符对(对 - >位置列表)。
  2. 对于每对,还存储在较大字符串中找到的出现次数。
  3. 获取搜索字中的所有字符对。
  4. 使用字符串中最不常出现的getten对,在每个位置检查匹配的搜索字词的剩余字符。
  5. 这就是它的要点。我想我可以使用长字符的地图,但现在我只是使用对。

    我能做些什么才能让它更快?我是以正确的方式接近这个吗?

2 个答案:

答案 0 :(得分:2)

字符串搜索是一个经过深入研究的主题:

  

http://en.wikipedia.org/wiki/String_searching_algorithm

您正在考虑寻找例如连续2个字符并存储该组合的频率,即使您使用平衡数据结构,这也是一项非常昂贵的操作。我真的没有看到如何将连续字符存储为预处理步骤对您有所帮助。

因此,显然有许多用于字符串搜索的算法。我觉得有趣的是,有一些算法甚至不需要扫描文本体中的每个字符。示例:如果您搜索单词'abbbbbc'并且您发现字符'd'作为文本正文的下一个字符,您可以立即跳出5个字符而无需查看它们是什么,然后如果下一个字符是'b'或'c'你显然必须回去查看你是否在跳跃时犯了错误,但如果没有,那么你跳过超过5个字符而不需要进行比较。然而,这很难实现,并导致有限自动机理论。

答案 1 :(得分:0)

另一个答案是指Boyer Moore算法。它使用子字符串上的预处理,而不是搜索材料。它被认为是一种快速的非索引搜索。

还有其他搜索算法可用于多次搜索同一文档。考虑Aho-Corasick。

但是,我使用的与您描述的类似的算法在下面的Python中实现。我们的想法是,对于每个元素,获取它出现的一组索引。然后进行搜索,使用子字符串中最不常见的字符作为参考点列表。循环遍历每个参考点的子字符串,在找不到索引时断开。

你应该测试一下,看它是否比Boyer Moore或其他算法更快。这个可以改进。这将是一个很好的练习,迟到五年。

class IndexRegistry(object):
    def __init__(self, iterable):
        self._store = defaultdict(set)
        for index, val in enumerate(iterable):
            self._store[ val ].add( index )

    def find(self, items):
        _, refIndex, refItem =  min( 
                                            [ ( len(self._store[item]), index, item ) 
                                                    for index, item in enumerate(items)
                                             ], 
                                            key=lambda el: el[0] 
                                        )

        for referenceIndex in self._store[ refItem ]:
            startIndex = referenceIndex - refIndex
            for itemIndex, item in enumerate(items):
                absIndex = startIndex + itemIndex
                if absIndex not in self._store[ item ]:
                    break #substring broken
            else: #no break
                yield startIndex

    def __contains__(self, items):
        try:
            next(self.find(items))
        except StopIteration:
            return False

        return True