上图可以看出,当匹配失败时,j要移动的下一个位置k。存在着这样的性质:序列2的位置j最前面的k个字符和序列1的位置i之前序列的最后k个字符是一样的。
接下来,我们看看 next 数组是如何在 O(m)O(m) 的复杂度内被预处理出来的。
假设有匹配串 aaabbab,我们来看看对应的 next 是如何被构建出来的。链接
def getnext(needle):
i, j, n = 1, 0, len(needle)
nnext = [0] * n
while i < n:
if needle[i] == needle[j]:
j += 1
nnext[i] = j
i += 1
elif j:
j = nnext[j - 1]
else:
nnext[i] = 0
i += 1
return nnext
needle="aaabbab"
getnext(needle)
#[0, 1, 2, 0, 0, 1, 0]
这就是整个 next 数组的构建过程,时空复杂度均为 O(m)O(m)。
至此整个 KMP 匹配过程复杂度是 O(m + n)O(m+n) 的。
// 方法一
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
a=len(needle)
b=len(haystack)
if a==0:
return 0
next=self.getnext(a,needle)
p=-1
for j in range(b):
while p>=0 and needle[p+1]!=haystack[j]:
p=next[p]
if needle[p+1]==haystack[j]:
p+=1
if p==a-1:
return j-a+1
return -1
def getnext(self,a,needle):
next=['' for i in range(a)]
k=-1
next[0]=k
for i in range(1,len(needle)):
while (k>-1 and needle[k+1]!=needle[i]):
k=next[k]
if needle[k+1]==needle[i]:
k+=1
next[i]=k
return next