leetcode(28)实现 strStr()-python 查找词匹配(求第二个字符串在第一个字符串的起始位置)

recording a day of vain
KMP AND Sunday查找匹配词算法,重点在于两个表怎么创建的
Sunday
一、匹配机制
每次将从目标字符串中提取的待匹配字符串(目标字符串[idx:idx+len(模式串)])模式串进行匹配:
若匹配,则返回当前索引idx
若不匹配,则查看待匹配字符串的后一位字符C
1.若C在模式串中,则索引idx变为 idx+偏移表[C]
2.若C不在模式串中,则索引idx变为idx+len(模式串)
不断循环,直到idx+len(模式串) > len(目标字符串)
二、偏移表的建立
很简单,就两种情况。
s h i f t [ w ] = { m − m a x { i < m ∣ P [ i ] = w } i f   w   i s   i n   P [ 0... m − 1 ] m + 1 o t h e r w i s e shift[w] = \begin{cases} {m-max\{ishift[w]={ mmax{ i<mP[i]=w}m+1if w is in P[0...m1]otherwise
1.如果待匹配字符串的后一位C在模式串中,则偏移量为第一种情况。max为模式串中出现的最右位置到尾部的距离
2.如果最后一位C不在模式串中,则整个偏移量为第二种情况,整个模式串长度+1
代码如下:

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
    #计算偏移表
    def calShiftMat(st):
    	dic ={
     }
    	for i in range(len(st)-1,-1,-1):
    		if not dic.get(st[i]):
    			dic[st[i]] = len(st)-i
    	dic['other'] = len(st) + 1
    	return dic
    if len(needle) > len(haystack):return -1
    if needle == '':return 0
    #偏移表预处理
    dic = calShiftMat(needle)
    idx = 0
    while idx+len(needle) <= len(haystack):
    	#待匹配字符串
    	str_cut = haystack[idx:idx+len(needle)]
    	#判断是否匹配
    	if str_cut == needle: #匹配成功
    		return idx
    	else:
    		if idx+len(needle) >= len(haystack):
    			return -1
    		#不匹配的话,根据下一个字符的偏移,移动idx
    		cur_c = haystack[idx+len(needle)]
    		if dic.get(cur_c):
    			idx += dic[cur_c]
    		else:
    			idx += dic['other']
    return -1 if idx+len(needle) >= len(haystack) else idx

KMP,利用已经匹配好的前几个字符。所以重点就在于《部分匹配表》的建立
移动位数 = 已匹配的字符数 - 对应的部分匹配值
对应的部分匹配值即为在匹配好的字符数中,前缀后缀词相等的那个词的长度(最长公共元素)。
如下,对于已经匹配好的ABCDABD字符,各个字对应的部分匹配值。leetcode(28)实现 strStr()-python 查找词匹配(求第二个字符串在第一个字符串的起始位置)_第1张图片
举个例子,后一个A为什么值为1 ;后一个B为什么值为2
ABCDA 前缀[A,AB,ABC,ABCD]后缀[BCDA,CDA,DA,A]共有 A,长度为1
ABCDAB 前缀[A,AB,ABC,ABCD,ABCDA]后缀[BCDAB,CDAB,DAB,AB,B]共有 AB,长度为2
这个链接讲KMP算法讲的很不错

class Solution:
    def strStr(self, t, p):
    	if not p :return 0
    	next = [0]*len(p)
    	def getNext(p,next):
    		next[0] = -1
    		i ,j= 0 ,-1
    		while i<len(p) -1:
    			if j==-1 or p[i]==p[j]:
    				i+=1
    				j+=1
    				next[i] = j
    			else:
    				j=next[j]  #为了生成next()这个部分配置表的
    	getNext(p,next)
    	i,j=0,0
    	while i<len(t) and j<len(p):
    		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

你可能感兴趣的:(leetcode(28)实现 strStr()-python 查找词匹配(求第二个字符串在第一个字符串的起始位置))