【问题标题】:Time complexity of LPS calculation of KMPKMP的LPS计算时间复杂度
【发布时间】:2020-07-30 17:51:18
【问题描述】:

虽然到处都提到我们在计算 KMP 的 LPS 时只回溯内循环中增加的数量,但不清楚为什么整体复杂度为 O(length(pat))。

【问题讨论】:

  • 这个问题是针对c++ 还是c

标签: algorithm search time-complexity knuth-morris-pratt


【解决方案1】:

KMP 维护两个索引:

k - 因为你有你的模式匹配 i — Text 中当前匹配的最新符号。

第一部分很简单,你只需要将符号与你的文本进行比较,如果它可以增加 i

如果他们不这样做,我们使用预先计算的前缀函数来缩短当前匹配的模式,并尝试在更短的版本上再次匹配相同的 x。以此类推,直到我们有一个匹配和 ++i,或者直到 k 达到 i 并且我们有一个全新的开始。

最坏的情况是,你将有 k 和 i 完全通过 Text 给出 2 * len(T) 步骤。

所以复杂度一直是 O(T + P)。在实际查找匹配项时,我们不依赖前缀的长度。这意味着,如果您对一个模式的多个匹配项进行 KMP,您仍然会得到 O(T + P)

【讨论】:

    【解决方案2】:

    看来我想通了。代码如下所示:

    while (j < len1) {
            if (needle[i] == needle[j]) {
                tab[j] = i+1;
                j++;
                i++;
            }
            else {
                if (i == 0) {
                    tab[j] = 0;
                    j++;
                }
                else
                    i = tab[i-1];
            }
        }
    

    所以基本上我们从不递减 j,在某些迭代 (else->else) 中我们不递增 j 并且 i 向后移动直到我们达到 0。 这种向后移动可以与 j 移动一样长。因此,如果 j 移动了 n 步,我们不能在最多 n 次迭代中增加 j。这使得总迭代次数为 n+n=2n 因此复杂度为 O(n)。

    【讨论】:

    • 请注意,例如,如果模式为 AAA,文本为 AABAABAAB...
    猜你喜欢
    • 1970-01-01
    • 2019-04-03
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    相关资源
    最近更新 更多