28. 实现 strStr()
题目描述:给你两个字符串
haystack和needle,请你在haystack字符串中找出needle字符串的第一个匹配项的下标(下标从0开始)。如果needle不是haystack的一部分,则返回-1。
解题思路:
- KMP算法的作用是在一个串中查找是否出现过另一个串。主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。
- 先写获取前缀数组next的函数。前缀数组是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。接着使用kmp算法。
代码:
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
def getNext(s):
n = len(s)
s_next = [0] * n
i = 0
j = 1
while j < n:
if s[j] == s[i]:
i += 1
s_next[j] = i
j += 1
else:
if i == 0:
s_next[j] == 0
j += 1
else:
i = s_next[i - 1]
return s_next
s_next = getNext(needle)
h_len = len(haystack)
n_len = len(needle)
i = 0
j = 0
while i < h_len:
if haystack[i] == needle[j]:
i += 1
j += 1
else:
if j == 0:
i += 1
else:
j = s_next[j - 1]
if j == n_len:
return i - j
return -1
459. 重复的子字符串
题目描述:给定一个非空的字符串
s,检查是否可以通过由它的一个子串重复多次构成。
解题思路:
- 简单做法是:将两个
ss连在一起,并移除第一个和最后一个字符,如果得到的字符串包含s,那么符合题目要求。 - KMP算法:使用
next数组,假设字符串s使用多个重复子串构成(这个子串是最小重复单位),重复出现的子字符串长度是x,所以s是由n * x组成。因为字符串s的最长相同前后缀的长度一定是不包含s本身,所以 最长相同前后缀长度必然是m * x,而且n - m = 1。所以如果nx % (n - m)x = 0,就可以判定有重复出现的子字符串。
代码:
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
def getNext(s):
n = len(s)
i = 0
j = 1
s_next = [0] * n
while j < n:
if s[j] == s[i]:
i += 1
s_next[j] = i
j += 1
else:
if i == 0:
s_next[j] = 0
j += 1
else:
i = s_next[i - 1]
return s_next
n = len(s)
s_next = getNext(s)
if s_next[-1] != 0 and n % (n - s_next[-1]) == 0:
return True
else:
return False