28. 找出字符串中第一个匹配项的下标
学习了KMP算法,其实算法本身还是比较直接的,利用前缀表内包含的已知信息去重来减少重复回滚比较的步骤。
- 前缀表:前缀表是一个数组,用于在发生冲突时确定下一步匹配应该从模式字符串的哪个位置开始。它记录了模式字符串中每个位置之前的子字符串的前缀和后缀的相等部分的长度。
- 使用KMP算法进行搜索:
- 初始化两个指针,分别指向文本字符串(haystack)和模式字符串(needle)。
- 遍历文本字符串,使用前缀表来决定在发生冲突时如何移动模式字符串的指针。
- 当模式字符串的指针移动到模式字符串的末尾时,表示找到了一个匹配。返回当前位置减去模式字符串长度,即匹配的起始索引。
- 如果遍历完文本字符串都没有找到匹配,返回-1。
class Solution:
def build_prefix_table(self, needle):
prefix_table = [0] * len(needle)
length = 0 # length of the previous longest prefix suffix
i = 1
while i < len(needle):
if needle[i] == needle[length]:
length += 1
prefix_table[i] = length
i += 1
else:
if length != 0:
length = prefix_table[length - 1]
else:
prefix_table[i] = 0
i += 1
return prefix_table
def strStr(self, haystack: str, needle: str) -> int:
if not needle:
return 0
prefix_table = self.build_prefix_table(needle)
i = 0 # index for haystack
j = 0 # index for needle
while i < len(haystack):
if needle[j] == haystack[i]:
i += 1
j += 1
if j == len(needle):
return i - j # found the match
elif i < len(haystack) and needle[j] != haystack[i]:
if j != 0:
j = prefix_table[j - 1]
else:
i += 1
return -1 # no match found
459. 重复的子字符串
方法一:s + s去头去尾,如果结论为真,至少还有一个s在字符串中。
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
return s in (s + s)[1:-1]
方法二:KMP算法,实际上,s的长度减去s的最长相等前后缀的长度必定能够被s的长度整除。
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
prefix_table = [0] * len(s)
length = 0
for i in range(1, len(s)):
while length > 0 and s[i] != s[length]:
length = prefix_table[length - 1]
if s[i] == s[length]:
length += 1
prefix_table[i] = length
return prefix_table[-1] != 0 and len(s) % (len(s) - prefix_table[-1]) == 0
今日总结:
kmp算法用于解决字符串匹配问题。
本文介绍了KMP算法,包括前缀表的构建和在字符串匹配中的应用。KMP算法通过减少回滚比较来提高效率,可用于查找字符串中第一个匹配项的下标及检测重复子字符串模式。





