KMP算法两个步骤
- 计算next数组
- 前缀表–最长相等前后缀 细细品味
字符串: a a b a a b a a b a a b
对应的prefix: [0,1,0,1,2,3,4,5,6,7,8,9]
- 根据next数组进行匹配
- prefix数组 0版本:nxt代表有最长前后缀的数量,刚好下标从0开始,回退到要匹配的nxt[j-1]处。j指向要匹配的地方
- next数组 -1版本:nxt代表已经匹配最长前后缀的下标,回退到nxt[j]处。j+1指向要匹配的地方
- 勉勉强强看懂,还需再细细品味
-prefix求的是最长相等前后缀–用来匹配回退。求prefix的时候,也是相同的匹配回退思路。需要再看几遍
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
def getNext(text):
N = len(text)
prefix = [0]*N
j = 0
for i in range(1,N):
while(j>0 and text[i]!=text[j]):
j = prefix[j-1]
if text[i]==text[j]:
j += 1
prefix[i] = j
return prefix
prefix = getNext(needle)
j = 0
for i in range(len(haystack)):
while(j>0 and haystack[i]!=needle[j]):
j = prefix[j-1]
if haystack[i] == needle[j]:
j += 1
if j == len(needle):
return i-len(needle)+1
return -1
459.重复的子字符
- 主要考察前缀表存的数字是否理解
- aabaabaab — nxt[-1] =6 (不减1版本)
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
def prefix(text):
N = len(text)
prefix = [-1]*N
j = -1
for i in range(1,N):
while(j>=0 and text[i]!=text[j+1]):
j = prefix[j]
if text[i] == text[j+1]:
j += 1
prefix[i] = j
return prefix
nxt = prefix(s)
return nxt[-1]!=-1 and len(s)%(len(s)-(nxt[-1]+1))==0
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
def prefix(text):
N = len(text)
prefix = [0]*N
j = 0
for i in range(1,N):
while(j>0 and text[i]!=text[j]):
j = prefix[j-1]
if text[i] == text[j]:
j += 1
prefix[i] = j
return prefix
nxt = prefix(s)
return nxt[-1]!=0 and len(s)%(len(s)-nxt[-1])==0
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
return (s + s).find(s, 1) != len(s)