改进文本搜索功能

Improving a text search function

本文关键字:功能 搜索 文本      更新时间:2023-10-16

我目前有一个文本搜索例程,看起来像这样:

    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循环后面更改变量在逻辑上是错误的。尽管我确信有更好的方法可以做到这一点,但我想不出任何方法。

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

任何关于我如何改进这一点的建议,无论是从性能上,还是从制作上,都将是最受欢迎的,这样它就不会让人觉得是一个拼凑的东西。

考虑到你在每个"大海捞针"中寻找几个"针",建议Boyer Moore的评论可能不是最好的。

当您搜索几个不同的目标时,通常更喜欢使用Aho-Corasick算法。这基本上是一个trie,但"扁平化"为表格式,添加了一些额外的"链接",以在一个匹配失败时优化继续搜索。使用它,您可以同时在特定的干草堆中搜索所有针头。至少从理论上讲,如果你在搜索N个字符串,这可能会使你的搜索速度加快大约N倍(通常比这略低,因为Aho-Corasick中的步骤比许多其他算法中的步骤复杂一点,但如果N很大,则幅度仍然很大)。

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

对于多字符串匹配,有许多Aho-Corasick的替代方案,例如Commentz-Walter算法和一种名为DAWG-MATCH的算法。后者在论文中产生了相当令人印象深刻的结果,但我还没有亲自实施或测试过,所以我有点犹豫是否过于强烈地推荐它。