题解 | #kmp算法#
kmp算法
https://www.nowcoder.com/practice/bb1615c381cc4237919d1aa448083bcc
暴力枚举法
时间复杂度:
- 外层循环遍历了所有可能的起始位置,时间复杂度为 O(len(T)-len(S)+1)
- 内层循环遍历了字符串 S 的所有字符,时间复杂度为 O(len(S))
- 总时间复杂度为 O((len(T)-len(S)+1) * len(S)) ------------ 这里不满足题目要求
空间复杂度:
- 使用了常数个变量,空间复杂度为 O(1)
class Solution:
def find(self , S: str, T: str) -> int:
# write code here
res = 0 # 出现的次数
for i in range(len(T)-len(S)+1):
temp = T[i:i+len(S)]
temp_res = 0
for j in range(len(S)):
if S[j] == temp[j]:
temp_res += 1
else:
break
if temp_res == len(S):
res += 1
return res
KMP算法
求next数组
# 最长公共前后缀,求next数组
class Solution(object):
def longestCommonPrefixAndSuffix(self, strs):
n = len(strs)
next = [0]*n
j = 0 # 要比较的下标
i = 1 # 当前的下标
while i < n:
if strs[i] == strs[j]: # 如果当前值与被比较值相等
j += 1
next[i] = j
i += 1
else: # 当前值与被比较值不相等
if j > 0: # 没有匹配到头j>0,j=next[j-1]
j = next[j-1]
elif j == 0: # 匹配到头j=0,当前值next[i] = 0 or =j, 然后当前值索引+1
next[i] = 0
i += 1
return next
obj = Solution()
print(obj.longestCommonPrefixAndSuffix('ababcabaa')) # [0, 0, 1, 2, 0, 1, 2, 3, 1]
# 也可以进一步改进成:
# 最长公共前后缀
class Solution(object):
def longestCommonPrefixAndSuffix(self, s):
n = len(s)
# 构建 next 数组
next = [0] * n
j = 0
for i in range(1, n):
while j > 0 and s[i] != s[j]:
j = next[j - 1]
if s[i] == s[j]:
j += 1
next[i] = j
print(next)
obj = Solution()
print(obj.longestCommonPrefixAndSuffix('ababcabaa')) # [0, 0, 1, 2, 0, 1, 2, 3, 1]
KMP应用next数组求解
# 计算模板串S在文本串T中出现了多少次
# @param S string字符串 模板串, 子串
# @param T string字符串 文本串, 主串
# @return int整型
class Solution:
def kmp(self , S: str, T: str) -> int:
# write code here
'构造next数组'
'''伪代码
if S[i]==S[j]:
i++,j++,next[i]=j
elif S[i]!=S[j]
if j==0, next[i]=0=j,i++
elif j!=0, j = next[j-1]
'''
j = 0 # 被比较的下标,初始化为0
next = [0]*len(S)
for i in range(1, len(S)): # i循环下标,初始化为1
if S[i] == S[j]:
j += 1
next[i] = j
else:
if j != 0:
while j != 0 and S[i] != S[j]:
j = next[j-1]
else:
next[i] = j
'子串S去匹配主串T'
'''伪代码
如果两个串的对应字符相等,索引都+1
如果不相等,子串的j=0时,主串的索引i+1;j不等于0时,j = next[j-1]
如果子串循环完成,次数+1,同时更新j,j = next[j-1]
'''
i, j = 0, 0
res = 0 # 次数
while i < len(T):
if T[i] == S[j]:
i+=1
j+=1
else:
if j > 0:
j = next[j-1]
else: # j == 0, 头一个就匹配失败
i += 1
if j == len(S):
res += 1 # 出现次数+1
j = next[j-1]
return res