返回
前端工程师的 LeetCode 之旅 -- KMP 字符串匹配算法(修正版)
前端
2023-10-05 04:35:57
KMP 算法:快速高效的字符串匹配利器
KMP 算法简介
在计算机科学中,字符串匹配是一个常见的任务,它涉及在文本字符串中查找指定模式字符串出现的位置。KMP 算法(也称为 Knuth-Morris-Pratt 算法)是一种高效的字符串匹配算法,由 Donald Knuth 和 Morris Pratt 于 1977 年提出。
KMP 算法原理
KMP 算法的核心在于利用部分匹配表 (PMT) 来追踪模式字符串的前缀和后缀之间的匹配关系。PMT 的长度与模式字符串的长度相等,其中 PMT[i] 表示模式字符串的前缀长度为 i 的最长后缀与模式字符串的最长公共前后缀的长度。
PMT 的计算过程如下:
- 初始化 PMT[0] 为 0。
- 对于 i 从 1 到模式字符串的长度 - 1,执行以下步骤:
- 令 j = PMT[i - 1]。
- 如果模式字符串的第 i 个字符与模式字符串的第 j 个字符相等,则 PMT[i] = j + 1。
- 如果模式字符串的第 i 个字符与模式字符串的第 j 个字符不相等,则重复步骤 2,直到 j = 0 或者模式字符串的第 i 个字符与模式字符串的第 j 个字符相等。
KMP 算法字符串匹配
PMT 计算完成后,即可使用它进行字符串匹配:
- 初始化 i = 0 和 j = 0。
- 如果文本字符串的第 i 个字符与模式字符串的第 j 个字符相等,则令 i = i + 1 和 j = j + 1。
- 如果文本字符串的第 i 个字符与模式字符串的第 j 个字符不相等,则令 j = PMT[j - 1]。
- 重复步骤 2 和步骤 3,直到 i = 文本字符串的长度或 j = 模式字符串的长度。
- 如果 j = 模式字符串的长度,则表示模式字符串在文本字符串的第 i - j + 1 个位置出现。
KMP 算法代码示例
def kmp_match(text, pattern):
"""
KMP 算法字符串匹配。
参数:
text: 文本字符串。
pattern: 模式字符串。
返回:
如果模式字符串在文本字符串中出现,则返回模式字符串在文本字符串中出现的所有位置的列表,否则返回空列表。
"""
# 计算部分匹配表。
pmt = [0] * len(pattern)
j = 0
for i in range(1, len(pattern)):
while j > 0 and pattern[i] != pattern[j]:
j = pmt[j - 1]
if pattern[i] == pattern[j]:
j += 1
pmt[i] = j
# 使用部分匹配表进行字符串匹配。
matches = []
i = 0
j = 0
while i < len(text):
while j > 0 and text[i] != pattern[j]:
j = pmt[j - 1]
if text[i] == pattern[j]:
j += 1
if j == len(pattern):
matches.append(i - len(pattern) + 1)
j = pmt[j - 1]
i += 1
return matches
if __name__ == "__main__":
text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
pattern = "ABC"
matches = kmp_match(text, pattern)
print(matches) # 输出:[0]
KMP 算法应用
KMP 算法由于其高效性,广泛应用于各种场景,包括:
- 文本编辑器
- 搜索引擎
- 病毒扫描软件
- 基因序列分析
- 数据挖掘
常见问题解答
1. KMP 算法与朴素算法相比有什么优势?
KMP 算法比朴素算法更有效率,因为它避免了在字符串匹配过程中重复比较。
2. PMT 在 KMP 算法中扮演什么角色?
PMT 记录了模式字符串前缀和后缀之间的匹配关系,帮助算法在文本字符串中快速定位模式字符串。
3. KMP 算法的时间复杂度是多少?
KMP 算法的时间复杂度为 O(n + m),其中 n 是文本字符串的长度,m 是模式字符串的长度。
4. 如何使用 KMP 算法在文本中查找多个模式字符串?
您可以使用 KMP 算法来逐个查找每个模式字符串,并在发现模式字符串出现的位置时将其记录下来。
5. KMP 算法在现实世界中有哪些实际应用?
KMP 算法用于各种应用中,包括文本搜索、基因匹配和数据分析。