解决字符串之间匹配的问题。
题目(leetcode 28):
KMP算法是一种空间换时间的算法。它的特点是主串的指针不往回走,利用存储好的信息,避免重复的运算。**在子串那构建一个PMT(Partial Match Table)表。PMT中的值是字符串的前缀集合(除去最后一个元素)与后缀集合(除去第一个元素)的交集中最长元素的长度。(元素集合不包括元素本身)**例如:‘ababa’。前缀集合(‘a’,‘ab’,‘aba’,‘abab’),后缀集合(‘baba’,‘aba’,‘ba’,‘a’),两个集合交集的最长元素为‘aba’,长度为3。说明这个子串从第一个元素开始走和从第三个元素开始走是一样的。(因为元素中有0索引,所以这个子串的表要全部向后移动一位方便计算)
具体做法:
我们要在子串(查询模式字符串中)建立KMP表。这样我们只需要遍历一遍主串即可完成查询。当我们遇到子串和主串字符不匹配的时候,在这个字符前,主串和子串是完全匹配上的,所以我们可以利用KMP的性质(主串的后n个字符和子串中前n个字符是相同的),把子串向前移动n位继续匹配。如图灰色部分就不用继续比较了:
计算子串的KMP表的时候也可以看成是字符串的匹配过程,即以模式字符串为主字符串,以模式字符串的前缀为目标字符串。一旦字符串匹配成功,那么当前的next值就是匹配成功的字符串的长度。
def strStr(self,t,p):
if not p:
return 0
_next = [0] * len(p)
def getNext(p,_next):
#想把KMP的值和子串位置对齐,让它第一位变为没有意义
_next[0] = -1
#开始求子串KMP的表,j = -1是为了当子串和主串的字符不相等时,往前走能让i + 1,跳出这个循环
i = 0
j = -1
while i < len(p) -1:
if j == -1 or p[i] == p[j]:
i += 1
j += 1
_next[i] = j
else:
#如果不匹配,就要利用KMP的性质,让子串的位置从头开始走j位,继续判断是否匹配
j = _next[j]
getNext(p,_next)
i = 0
j = 0
while i < len(t) and j < len(p):
#子串KMP表中第一个为-1,所以跟上面一样也是为了跳出循环
if j == -1 or t[i] == p[j]:
i += 1
j += 1
else:
j = _next[j]
if j == len(p):
#主串上的最后的位置-子串上的长度
return i - j
return -1