894 字
4 分钟
代码随想录算法训练营第八天 | 字符串 Part02

字符串 Part02 笔记#


151. 翻转字符串里的单词#

LeetCode 151. 翻转字符串里的单词

class Solution:
def reverseWords(self, s: str) -> str:
# 将字符串按空格分割成单词列表
s = s.split()
left, right = 0, len(s) - 1
# 使用双指针反转单词列表
while left < right:
s[left], s[right] = s[right], s[left]
left += 1
right -= 1
return ' '.join(s)

卡码网:55. 右旋转字符串#

题目链接

import sys
input = sys.stdin.read
# 右旋转字符串,当字符串长度小于旋转次数时,实际旋转次数为长度取模
def main():
data = input().split()
num = int(data[0])
s = data[1]
length = len(s)
num = num % length
res = []
res.append(s[length - num:])
res.append(s[:length - num])
print(''.join(res))
if __name__ == "__main__":
main()

KMP 算法#

  • KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法。
  • 通过构建 部分匹配表(前缀表),避免重复匹配字符,从而提升搜索效率。
  • 时间复杂度:O(n + m),其中 n 为文本串长度,m 为模式串长度。

应用场景#

  1. 在大文本中查找子串

    • 最基础的用途,替代暴力匹配。
  2. 实现 strStr() 函数

    • LeetCode 28,查找子串首次出现的位置。
  3. 检测字符串是否由重复子串组成

    • LeetCode 459,判断字符串是否能通过子串重复构成。
  4. 字符串周期性检测

    • 判断字符串的最小循环节,比如 DNA 重复序列。
  5. 最小字符串构造问题

    • 构造最短的重复串,使得一个字符串成为其前缀或后缀。
  6. 前后缀匹配、构建自动机状态转移表

    • KMP 中的 next 数组本质就是一种状态机转移的前缀优化,常用于构建有限状态机(FSM)模型。
  7. 字符串压缩 / 编码

    • 如在数据压缩算法中,寻找重复模式进行压缩(与 Z-algorithm、Boyer-Moore 可组合)。
  8. 回文串构造与检测(改造版)

    • 例:添加最少字符使字符串变为回文(可将 rev(s) + "#" + s 套用 KMP)。

KMP 算法模板#

# 获取模式串的前缀表(部分匹配表)
def getNext(s):
next = [0]
length = 0
i = 1
while i < len(s):
if s[i] == s[length]:
length += 1
next.append(length)
i += 1
else:
if length == 0:
next.append(0)
i += 1
else:
length = next[length - 1]
return next
# 主函数,查找模式串在文本串中出现的位置
def strStr(string, pattern):
next = getNext(pattern)
i, j = 0, 0
while i < len(string):
if string[i] == pattern[j]:
i += 1
j += 1
elif j > 0:
j = next[j - 1]
else:
i += 1
if j == len(pattern):
return i - j
return -1

28. 实现 strStr()#

LeetCode 28. 实现 strStr()

class Solution:
def strStr(self, haystack: str, needle: str) -> int:
next = self.getNext(needle)
i, j = 0, 0
while i < len(haystack):
if haystack[i] == needle[j]:
i += 1
j += 1
# 如果 j 达到 needle 的长度,说明找到了匹配
if j == len(needle):
return i - j
elif j > 0:
j = next[j - 1]
else:
i += 1
# 如果 j 没有达到 needle 的长度,说明没有找到匹配
return -1
def getNext(self, s):
next = [0]
length = 0
i = 1
while i < len(s):
if s[i] == s[length]:
length += 1
next.append(length)
i += 1
else:
if length == 0:
next.append(0)
i += 1
else:
length = next[length - 1]
return next

459. 重复的子字符串#

LeetCode 459. 重复的子字符串

class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
next = self.getNext(s)
n = len(s)
# 如果 next 数组的最后一个值大于 0,且 n 能被 n - next[-1] 整除,则说明存在重复的子字符串
return next[-1] > 0 and n % (n - next[-1]) == 0
def getNext(self, s):
next = [0]
length = 0
i = 1
while i < len(s):
if s[length] == s[i]:
i += 1
length += 1
next.append(length)
else:
if length == 0:
next.append(0)
i += 1
else:
length = next[length - 1]
return next
代码随想录算法训练营第八天 | 字符串 Part02
https://fuwari.vercel.app/posts/code_musings_day_eight/
作者
Jarrett
发布于
2025-06-19
许可协议
CC BY-NC-SA 4.0