![9ee4218af577c9e9d54a667ae15be456.png](https://i-blog.csdnimg.cn/blog_migrate/0bc921d3304fa50b6127836cb56b58b3.jpeg)
说起来KMP算法我在大学里就见过,但是完全没理解。
毕业以后看算法导论也是一头雾水。
最近心血来潮想研究研究,看了个
视频www.bilibili.com发现一下就懂了。
原理你们可以点这个视频链接看看。
我这里简单讲解一下,里面最重要的概念就是模式串的最长公共前后缀和next数组。
最长公共前后缀: 指的是小于该字符串长度的首尾相同的字符串,如果有多个取最长的。
假设有一个字符串 aba 最长公共前后缀:a ,长度为 1
abab 最长公共前后缀:ab ,长度为 2
ababa 最长公共前后缀:aba ,长度为 3
next数组:
就是通过模式的最长公共前后缀的长度组合起来的
假设有个模式串 ababac 记录每个元素的最长公共前后缀长度,组成数组
a 不存在公共前后缀 0
ab 不存在公共前后缀 0
aba a 1
abab ab 2
ababa aba 3
ababac 不存在 0
[0,0,1,2,3,0]之后去掉最后一个,在前面补充-1,[-1,0,0,1,2,3] 这就是ababac的next数组
然后根据视频里的说法,写了段kmp的实现。
当然可能写的有问题,因为我只测了3个testcase。
def kmp(str, pattern):
next = nextkmp(pattern)
i,j = 0,0
while i < len(str):
c = str[i]
if c == pattern[j] :
if j == len(pattern) - 1 :
return i - len(pattern) + 1
else:
i += 1
j += 1
continue
else:
j = next[j]
if j==-1:
j = 0
i += 1
return -1
def nextkmp(pattern):
nextarr = [0]*len(pattern)
nextarr[0] = -1
nextarr[1] = 0
for i in range(2,len(pattern)):
nextarr[i] = getnext(i,pattern)
return nextarr
def getnext(i,pattern):
m = i - 1
while m > 0:
if pattern[:m]==pattern[i-m:i]:
return m
else :
m-=1
return m
print(kmp('abcabcabcabe','abcabcabe'))
print(kmp('abcabcabcabe','abcabe'))
print(kmp('abcabcabcabe','abe'))