KMP算法的时间复杂度

时间:2014-02-09 05:04:49

标签: c++ string algorithm time-complexity

我正在尝试使用KMP算法实现strstr。这是维基百科中给出的算法。 KMP算法的时间复杂度为O(n),其中n是较大字符串的大小。

vector<int> KMP(string S, string K)
{
    vector<int> T(K.size() + 1, -1);
    vector<int> matches;

    if(K.size() == 0)
    {
        matches.push_back(0);
        return matches;
    }
    for(int i = 1; i <= K.size(); i++)
    {
        int pos = T[i - 1];
        while(pos != -1 && K[pos] != K[i - 1]) pos = T[pos];
        T[i] = pos + 1;
    }

    int sp = 0;
    int kp = 0;
    while(sp < S.size())
    {
        while(kp != -1 && (kp == K.size() || K[kp] != S[sp])) kp = T[kp];
        kp++;
        sp++;
        if(kp == K.size()) matches.push_back(sp - K.size());
    }

    return matches;
}

我不明白这个算法的复杂程度如何是O(n)。任何人都可以解释这段代码的复杂性是如何O(n)?

1 个答案:

答案 0 :(得分:2)

我认为你担心的是,两种情况下的内循环每次外循环迭代最多可执行m次,从而导致你提到的最坏情况复杂性。事实上,这不可能发生。

归纳地看第一个循环通知,因为T []初始化为-1,我们得到T [0]&lt; 0,T [1]&lt; 1,...你可以看到我们实际上有T [i]&lt;我有意义,因为T [i]是一个指向我们正在搜索的字符串的指针。

现在转到第二个嵌套循环,看看每个外循环迭代只增加一次kp,而内部while循环只能减少它。由于kp低于-1并且从0开始,在整个方法的整个生命周期中,我们总共只能执行一次内循环迭代,而不是外循环迭代,因为否则kp最终会小于 - 1。所以第二个嵌套循环只能花费总共O(n)。

第一个嵌套循环看起来比较棘手,直到你注意到在外循环开始时从T [i-1]读取pos,然后在结尾写为T [i] = pos + 1,所以pos是等价的我们刚刚分析了嵌套循环中的kp,并且相同的参数表明成本最多为O(K.size())。