【发布时间】:2020-07-30 17:51:18
【问题描述】:
虽然到处都提到我们在计算 KMP 的 LPS 时只回溯内循环中增加的数量,但不清楚为什么整体复杂度为 O(length(pat))。
【问题讨论】:
-
这个问题是针对
c++还是c?
标签: algorithm search time-complexity knuth-morris-pratt
虽然到处都提到我们在计算 KMP 的 LPS 时只回溯内循环中增加的数量,但不清楚为什么整体复杂度为 O(length(pat))。
【问题讨论】:
c++ 还是c?
标签: algorithm search time-complexity knuth-morris-pratt
KMP 维护两个索引:
k - 因为你有你的模式匹配 i — Text 中当前匹配的最新符号。
第一部分很简单,你只需要将符号与你的文本进行比较,如果它可以增加 i
如果他们不这样做,我们使用预先计算的前缀函数来缩短当前匹配的模式,并尝试在更短的版本上再次匹配相同的 x。以此类推,直到我们有一个匹配和 ++i,或者直到 k 达到 i 并且我们有一个全新的开始。
最坏的情况是,你将有 k 和 i 完全通过 Text 给出 2 * len(T) 步骤。
所以复杂度一直是 O(T + P)。在实际查找匹配项时,我们不依赖前缀的长度。这意味着,如果您对一个模式的多个匹配项进行 KMP,您仍然会得到 O(T + P)
【讨论】:
看来我想通了。代码如下所示:
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)。
【讨论】: