Day 09
字符串
今天两道KMP:KMP功能,在一个字符串中找到是否出现另一个字符串
本篇会再更新~
6. 实现strStr(力扣28)
- 题目描述:找出字符串中第一个匹配项的下标heystack干草堆,needle针,大海捞针~
- 思路:KMP算法
- B站一个讲的很好的视频
- 整体思路:假设有主串n和模式串m,在暴力算法当中,每当主串与模式串不匹配,我们就需要对主串和模式串同时回溯,时间复杂度为O(n*m)
- 可以改进的地方在于:当我匹配到模式串的某个部分不同时,我就无需重全部从头遍历:当主串匹配到A,从串匹配到C,起码来讲,主串一定是经历过AB的,这个AB在我接下来要匹配的时候,可以和模式串的开头AB对应上,所以我就看看下一个和开头AB的后一个能不能对应上。(看不懂就看看视频)
- python语法细节
- python实现
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
next_ = [None]*len(needle)
self.build_next(next_,needle)
i=0
j=0
while i<=len(haystack):
if(j==len(needle)):
return i-len(needle)
elif(i == len(haystack)):
return -1
elif(haystack[i]==needle[j]):
# print(i,j)
i +=1
j+=1
else:
if(j==0):
i+=1
else:j = next_[j-1]
def build_next(self,next,s):
#首个字符串的最长公共前缀为0,直接赋值
next[0]=0
max_prex = 0
#首个字符记过了,我们从第二个字符开始,下标为1
i = 1
#i不回溯,因此算法的时间复杂度为O(N)
while i<len(s):
#i遍历到的待求解字符和当前最长前缀的下一个字符相等时
if(s[i]==s[max_prex]):
#那么i的最长前缀就是当前最长前缀+1
next[i]=max_prex+1
#可以遍历下一个数了
i+=1
#当前最长前缀长度+1了哦
max_prex+=1
#i遍历到的带求解字符和当前最长前缀的下一个字符不等
#那就在这个前缀上找找关系,这一小块也不白遍历,利用一下前缀中的重复元素
else:
#都找到第一个元素了,都没重复的,那就是0了
if max_prex == 0:
next[i]=0
#遍历下一个数
i+=1
else:
#m没到0就还能抢救一下,再看看前缀里有没有重复元素
max_prex = next[max_prex-1]
7. 重复的子字符串(力扣459)
- 题目描述:
- 思路:这道题可以理解为:从1到中部这些位置开始的字符串,是否有可能包含从0开始的字符串。因此我们还是先求s的next数组(其实求一半就行,因为子串不可能比一半还长)。然后以1开头作为主串进行遍历,如果相同就主串子串同时向后,如果不同,那么子串不用全部回溯到0,只需要回溯到next数组说的值就可以。最终判断,right-left就是子串长度,如果left可以被长度整出,就位真。
- python语法细节:
- python实现:
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
next_ = [None]*len(s)
self.build_next(next_,s)
print(next_)
if(len(s)==1):
return False
left = 0
right = 1
while(right<len(s)):
print(left,right)
if(s[left]==s[right]):
left +=1
right +=1
else:
if left==0:
right+=1
else:
left = next_[left-1]
l = right - left
if (l!=0 and left%l==0 and left!=0):
return True
else:
return False
def build_next(self,next,s):
i = 1
max_len = 0
next[0] = 0
while(i<len(s)):
if(s[i]==s[max_len]):
max_len +=1
next[i]=max_len
i +=1
else:
if(max_len==0):
next[i]=0
i+=1
else:
max_len = next[max_len-1]