一、KMP算法解决的问题:
KMP算法主要解决字符串匹配的问题;当遇到冲突的字符时候,由于前缀表记录了之前的匹配信息,因此模式串不需要从头开始匹配;(从文本串中寻找模式串)
二、KMP算法的核心:
KMP算法的核心是找到前缀表(前缀表中存储了第i个索引以及其之前的子串的最大相等前后缀),然后利用前缀表进行回退。
当匹配到某个字符发生冲突时,找到其前一个字符在前缀表中(next数组中)对应索引位置处的值,然后模式串索引回退到指定位置,重新开始匹配。
三、最大相等前后缀
前缀:不包含末尾字符的所有子串;
后缀:不包含首字符的所有子串;
例如:a 的最大相等前后缀为0;aa的最大相等前后缀为1;aab的为0;aaba的为1;aabaa的为2;
四、前缀表的求解
1.程序需要处理三种情况:初始化、当前后缀相同的情况、前后缀不相同的情况;具体实现看代码;
2.有了前缀表之后就可以进行匹配了;
五、KMP算法解决leetcode 28
1.题目描述:
leetcode链接:https://leetcode-cn.com/problems/implement-strstr/
2.代码
class Solution:
#获取前缀表(next数组)
def getNext(self,s):
next_lst = [0]*len(s)
qz = 0
next_lst[0] = qz
for hz in range(1,len(s)):
#前后缀不相等的情况
while s[qz]!= s[hz] and qz>0:
#回退
qz = next_lst[qz-1]
if s[qz] == s[hz]:
#前后缀相等的情况
qz +=1
#前缀的索引+1就是当前后缀及其前面字符串的最大相等前后缀
next_lst[hz] = qz
return next_lst
def strStr(self, haystack: str, needle: str) -> int:
if len(needle) ==0:
return 0
needle = list(needle)
haystack = list(haystack)
next_lst = self.getNext(needle) #获取到next数组
#进行比较
i,j=0,0
while i<=len(haystack)-1 and j<=len(needle)-1:
#终止条件,只要任意一个数组遍历完就中止,终止后判断如果是模式串遍历完成,则说明文本串中存在模式串,否则输出-1
if haystack[i] == needle[j]:
j+=1
else:
#如果j小于1则j为0
if j>=1:
j = next_lst[j-1]
i -=1 #遇到矛盾的字符串,i不动,j回退,但由于if语句之外有个i+=1,因此这里减去1
else:
j = 0
i +=1
#终止后判断
if j==len(needle):
return i-j
else:
return -1
六、参考
KMP算法详解参考: