为什么 KMP 的正常情况复杂度为 O(N)?
Why is the normal case complexity of KMP O(N)?
在终于理解了 KMP 算法之后,它的复杂性仍然不清楚。
对于模式 M 的长度和文本 N 的长度,我知道,在最坏的情况下它是 O(N+M) (仍然无法解释,为什么),但为什么它是 O(N) 在平均案件?
预先感谢您的帮助。
在这个回答中,我将解决你问题的这一部分。
For the length of the pattern M and for the length of the text N, I know, in
worst case it's O(N+M) (still can't explain, why)
我将尝试解释为什么计算失败函数(KMP算法中的预处理步骤)需要线性时间,您可以对字符串匹配部分的运行时间进行类似的分析算法。
代码(取自here):
KNUTH-MORRIS-PRATT FAILURE (P)
Input : Pattern with N characters
Output: Failure function f for pattern P
i ← 1
matched ← 0
f(0) ← 0
while i < N do
if P[matched] = P[i]
f(i) ← j +1
i ← i +1
matched← matched + 1
else if matched>0
matched ← f(matched - 1)
else
f(i) ← 0
i ← i +1
运行计算失败函数的时间=while循环的最大迭代次数
Number of iterations of while loop = Number of successful matches +
Number of unsuccessful matches
Let's call this statement (1)
令 N = 模式的长度。
Number of successful matches<=N
(Check for instance, this pattern "aaaa")
Let's call this statement (2)
不成功的匹配次数有点棘手。
让我们举个例子模式"aaabcaaabce"
对于此模式,数组为:
| 0 | 1 | 2 | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 0 |
注意在索引 3 中,当不匹配发生时,当我们下降到值 0 时,我们最多可以做 2 个不匹配,或者换句话说,我们只能做与匹配的字符数一样多的不匹配所以远.
因此每次索引 i 发生不匹配时,该索引 i 的最大不匹配数最多可以是目前匹配的字符数(索引 i-1)。
直观地说,整个数组中匹配的字符数就是数组中非零的条目。因为非零条目意味着匹配。因为,
最大匹配失败数 = 匹配字符数
=> 整个数组中不成功的最大匹配数
= 数组中最大字符匹配数
= 数组中非零的条目数
<=N
Thus, Maximum number of unsuccessful matches over the array <=N
Let's call this statement (3)
将 (1)、(2) 和 (3) 放在一起:
总 运行 时间 = 运行 成功匹配的时间 + 运行 不成功匹配的时间
运行时间<=N+N
运行 时间 <= 2*N
Running time for computing failure function = O(N)
在终于理解了 KMP 算法之后,它的复杂性仍然不清楚。 对于模式 M 的长度和文本 N 的长度,我知道,在最坏的情况下它是 O(N+M) (仍然无法解释,为什么),但为什么它是 O(N) 在平均案件? 预先感谢您的帮助。
在这个回答中,我将解决你问题的这一部分。
For the length of the pattern M and for the length of the text N, I know, in worst case it's O(N+M) (still can't explain, why)
我将尝试解释为什么计算失败函数(KMP算法中的预处理步骤)需要线性时间,您可以对字符串匹配部分的运行时间进行类似的分析算法。
代码(取自here):
KNUTH-MORRIS-PRATT FAILURE (P)
Input : Pattern with N characters
Output: Failure function f for pattern P
i ← 1
matched ← 0
f(0) ← 0
while i < N do
if P[matched] = P[i]
f(i) ← j +1
i ← i +1
matched← matched + 1
else if matched>0
matched ← f(matched - 1)
else
f(i) ← 0
i ← i +1
运行计算失败函数的时间=while循环的最大迭代次数
Number of iterations of while loop = Number of successful matches + Number of unsuccessful matches
Let's call this statement (1)
令 N = 模式的长度。
Number of successful matches<=N
(Check for instance, this pattern "aaaa")Let's call this statement (2)
不成功的匹配次数有点棘手。
让我们举个例子模式"aaabcaaabce"
对于此模式,数组为:
| 0 | 1 | 2 | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 0 |
注意在索引 3 中,当不匹配发生时,当我们下降到值 0 时,我们最多可以做 2 个不匹配,或者换句话说,我们只能做与匹配的字符数一样多的不匹配所以远.
因此每次索引 i 发生不匹配时,该索引 i 的最大不匹配数最多可以是目前匹配的字符数(索引 i-1)。
直观地说,整个数组中匹配的字符数就是数组中非零的条目。因为非零条目意味着匹配。因为,
最大匹配失败数 = 匹配字符数
=> 整个数组中不成功的最大匹配数
= 数组中最大字符匹配数
= 数组中非零的条目数
<=N
Thus, Maximum number of unsuccessful matches over the array <=N
Let's call this statement (3)
将 (1)、(2) 和 (3) 放在一起:
总 运行 时间 = 运行 成功匹配的时间 + 运行 不成功匹配的时间
运行时间<=N+N
运行 时间 <= 2*N
Running time for computing failure function = O(N)