返回

前端工程师的 LeetCode 之旅 -- KMP 字符串匹配算法(修正版)

前端

KMP 算法:快速高效的字符串匹配利器

KMP 算法简介

在计算机科学中,字符串匹配是一个常见的任务,它涉及在文本字符串中查找指定模式字符串出现的位置。KMP 算法(也称为 Knuth-Morris-Pratt 算法)是一种高效的字符串匹配算法,由 Donald Knuth 和 Morris Pratt 于 1977 年提出。

KMP 算法原理

KMP 算法的核心在于利用部分匹配表 (PMT) 来追踪模式字符串的前缀和后缀之间的匹配关系。PMT 的长度与模式字符串的长度相等,其中 PMT[i] 表示模式字符串的前缀长度为 i 的最长后缀与模式字符串的最长公共前后缀的长度。

PMT 的计算过程如下:

  1. 初始化 PMT[0] 为 0。
  2. 对于 i 从 1 到模式字符串的长度 - 1,执行以下步骤:
    • 令 j = PMT[i - 1]。
    • 如果模式字符串的第 i 个字符与模式字符串的第 j 个字符相等,则 PMT[i] = j + 1。
    • 如果模式字符串的第 i 个字符与模式字符串的第 j 个字符不相等,则重复步骤 2,直到 j = 0 或者模式字符串的第 i 个字符与模式字符串的第 j 个字符相等。

KMP 算法字符串匹配

PMT 计算完成后,即可使用它进行字符串匹配:

  1. 初始化 i = 0 和 j = 0。
  2. 如果文本字符串的第 i 个字符与模式字符串的第 j 个字符相等,则令 i = i + 1 和 j = j + 1。
  3. 如果文本字符串的第 i 个字符与模式字符串的第 j 个字符不相等,则令 j = PMT[j - 1]。
  4. 重复步骤 2 和步骤 3,直到 i = 文本字符串的长度或 j = 模式字符串的长度。
  5. 如果 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 算法用于各种应用中,包括文本搜索、基因匹配和数据分析。