改进文本搜索功能

时间:2014-11-05 01:34:01

标签: c++ performance full-text-search

我目前有一个文本搜索例程,如下所示:

    unsigned match = 0;
    for(unsigned position=0;position<haystack_length;position++) {
        if (haystack[position]==needle[match]) {
            match++;
            if (match==needle_length) {
                // report match at position
                match = 0; // keep on finding matches
            }
        }
        else {
            position -= match;
            match = 0;
        }
    }

我的直觉说我在这里做错了什么......特别是,似乎在进行了部分匹配之后,试图重置“定位”。返回到任何匹配发生之前的位置使得这是一个O(nm)算法作为最坏的情况,n是干草堆的长度,m是针的长度。而且,在某种程度上,它在某种程度上改变了for循环背后的那个变量,这让我感到震惊。虽然我确信有更好的方法可以做到这一点,但我无法想到。

我的具体用例,如果可以对其进行任何优化,我将需要在许多不同的草堆中搜索几个不同的针,并且我将在每个草堆中搜索的针组将是相同。

关于我如何才能提高性能的建议,以及为了让它感觉不像kludge而受到欢迎的任何建议都会受到欢迎。

1 个答案:

答案 0 :(得分:0)

鉴于你在每个“草堆”中搜索了几个“针”,建议Boyer-Moore 可能的评论并不是最好的。

当您搜索多个不同的目标时,通常更喜欢使用Aho-Corasick算法。这基本上是一个trie,但是“展平”成表格式,添加了一些额外的“链接”以优化在一次匹配失败时继续搜索。使用它,您可以同时在特定的大海捞针中搜索所有针。至少从理论上讲,如果你正在搜索N个字符串,这可能会使你的搜索速度提高大约N倍(通常略低于此值,因为Aho-Corasick中的步骤比许多其他算法稍微复杂一些,但如果N很大,则保证金仍然可能非常大。)

之后的下一个显而易见的步骤可能是在干草堆中并行搜索。为Aho-Corasick建立一个表格,搜索你关心的针头,将其复制到每个线程,然后线程搜索干草堆。

Aho-Corasick有多种替代方法可用于多字符串匹配,例如Commentz-Walter算法和一种名为DAWG-MATCH的算法。后者在its paper中产生了相当令人印象深刻的结果,但我没有亲自实现或测试它,所以我有点犹豫推荐它太强烈了。