(带有示例)为什么KMP字符串匹配O(n)。应该不是O(n * m)吗?

时间:2019-06-20 08:51:02

标签: algorithm time-complexity string-matching knuth-morris-pratt

为什么KMP O(n + m)?

我知道这个问题可能在这里被问了一百万遍,但是我没有找到能说服我/我理解的解决方案,也没有找到与我的例子相符的问题。

/**
 * KMP algorithm of pattern matching.
 */
public boolean KMP(char []text, char []pattern){

    int lps[] = computeTemporaryArray(pattern);
    int i=0;
    int j=0;
    while(i < text.length && j < pattern.length){
        if(text[i] == pattern[j]){
            i++;
            j++;
        }else{
            if(j!=0){
                j = lps[j-1];
            }else{
                i++;
            }
        }
    }
    if(j == pattern.length){
        return true;
    }
    return false;
}

n =文字大小
m =图案大小

我知道为什么它的+ m是创建lsp数组进行查找所需的运行时间。我不确定为什么我上面传递的代码是O(n)。

我看到上面的“ i”在不匹配且j!= 0时总是向前前进EXCEPT。在那种情况下,我们可以对while循环进行迭代,其中i不会向前移动,因此它并不完全O(n)

如果lps数组像[1,2,3,4,5,6,0]那样递增。如果我们未能在索引6处匹配,则j更新为5,然后更新为4,然后更新为3 ....等,然后我们将有效地进行m次额外的迭代(假定所有不匹配)。这可以发生在每个步骤。

所以看起来像

for (int i = 0; i < n; i++) {
    for (int j = i; j >=0; j--)  {
    }
}

并把所有可能的i j组合称为aka状态将需要一个n m数组,因此运行时不会是O(n m)。

那么我的代码读取错误吗,或者for循环的运行时分析错误,或者我的示例是不可能的?

1 个答案:

答案 0 :(得分:0)

实际上,现在我考虑了。它是O(n + m)。只是将其可视化为两个窗口在移动。