返回
弦外之音:用30行代码实现KMP算法,轻松玩转字符串匹配!
人工智能
2024-02-22 07:38:27
在浩瀚的算法数据结构王国里,今天我们迎来了一位新成员——KMP算法。它可不是什么视频播放器,更不是让你去观摩毛片的大杀器,而是由Knuth、Morris和Pratt这三位大牛的名字合称而来。老外很喜欢用人名来命名算法或者是定理,数学里就有一堆,比如高斯定理、欧拉函数等等。
KMP算法是一种高效的字符串匹配算法,它能够快速地找到一个字符串在另一个字符串中的位置。它在文本编辑、搜索引擎、生物信息学等领域有着广泛的应用。在今天的文章中,我们将从KMP算法的原理出发,逐步解析它的实现细节,并用精简的30行代码实现该算法。
KMP算法原理
KMP算法的核心思想是利用失配函数来进行优化。失配函数是一个数组,它存储了每个位置的失配值。失配值是指当模式串和目标串在该位置匹配失败时,模式串需要移动的位数。通过利用失配函数,KMP算法可以在匹配失败时快速地跳过不必要的比较,从而提高匹配效率。
KMP算法实现
-
前缀表构建:
首先,我们需要构建一个前缀表。前缀表是一个大小为模式串长度的数组,它存储了模式串每个前缀的失配值。前缀表的构建过程如下:
- 将前缀表的第一个元素设置为0。
- 对于模式串的每个字符,从第二个字符开始:
- 将当前字符与前缀表中与当前字符位置相对应的元素进行比较。
- 如果相等,则将前缀表中当前字符位置的元素加1。
- 如果不相等,则将前缀表中当前字符位置的元素设置为前缀表中与当前字符前一个字符位置的元素。
-
字符串匹配:
构建好前缀表后,就可以进行字符串匹配了。匹配过程如下:
- 将模式串的第一个字符与目标串的第一个字符进行比较。
- 如果相等,则将模式串的第二个字符与目标串的第二个字符进行比较。
- 如果不相等,则将模式串的第一个字符与目标串的第二个字符进行比较。
- 重复步骤2和步骤3,直到模式串匹配成功或匹配失败。
如果模式串匹配成功,则返回模式串在目标串中的起始位置。如果模式串匹配失败,则返回-1。
KMP算法代码实现
def kmp_search(pattern, text):
"""
KMP算法实现字符串匹配
Args:
pattern: 模式串
text: 目标串
Returns:
如果模式串在目标串中找到,则返回模式串在目标串中的起始位置,否则返回-1
"""
# 构建前缀表
prefix_table = build_prefix_table(pattern)
# 字符串匹配
i = 0 # 模式串的当前位置
j = 0 # 目标串的当前位置
while i < len(pattern) and j < len(text):
if pattern[i] == text[j]:
i += 1
j += 1
else:
if i == 0:
j += 1
else:
i = prefix_table[i - 1]
if i == len(pattern):
return j - len(pattern)
else:
return -1
def build_prefix_table(pattern):
"""
构建前缀表
Args:
pattern: 模式串
Returns:
前缀表
"""
prefix_table = [0] * len(pattern)
i = 1
j = 0
while i < len(pattern):
if pattern[i] == pattern[j]:
prefix_table[i] = j + 1
i += 1
j += 1
else:
if j == 0:
prefix_table[i] = 0
i += 1
else:
j = prefix_table[j - 1]
return prefix_table
if __name__ == "__main__":
pattern = "ABCD"
text = "AABCAABCD"
result = kmp_search(pattern, text)
print("模式串在目标串中的起始位置:", result)
结语
KMP算法是一种高效的字符串匹配算法,它利用失配函数来进行优化,从而提高了匹配效率。在本文中,我们介绍了KMP算法的原理、实现细节和代码实现。希望通过本文,你能对KMP算法有更深入的了解,并能够将其应用到实际场景中。