浅谈Python描述数据结构之KMP篇
简介
本篇文章将着重介绍KMP算法,其中包含KMP算法的基本原理、实现步骤以及Python代码实现示例。KMP算法是一种高效的字符串匹配算法,它可以在O(m+n)的时间内完成字符串的匹配操作,其中m和n分别为主串和模式串的长度。
基本原理
KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,它的基本思想是通过“部分匹配表”来避免不必要的比较操作。具体来说,它在匹配过程中,当某个字符匹配失败时,不是直接跳转到下一个字符进行比较,而是根据已匹配的结果来确定下一个比较的位置。这个过程中,部分匹配表就发挥了重要作用,它能够提供已匹配的信息,以及在匹配失败时的跳转位置。
实现步骤
KMP算法的实现步骤主要包括以下几个部分:
- 构建部分匹配表
- 在主串和模式串中进行匹配
- 根据部分匹配表调整匹配位置
其中,构建部分匹配表是整个算法中最重要的一步,需要单独解释。
构建部分匹配表
部分匹配表是模式串本身的一个数组,用来储存模式串的每个位置上,从头开始的子串的最长公共前后缀长度。具体地,设模式串为p,p的长度为m,则部分匹配表的长度也为m。在第i个位置上,部分匹配表的值表示p[:i+1]这个子串的最长公共前后缀长度。需要注意的是,这里的公共前后缀必须是非自身重复的,否则会出现算法错误。以p="ABCDABD"为例,它的部分匹配表为:
字符串 | A | B | C | D | A | B | D |
---|---|---|---|---|---|---|---|
部分匹配表 | 0 | 0 | 0 | 0 | 1 | 2 | 0 |
在主串和模式串中进行匹配
在进行匹配时,我们将主串和模式串对齐,从左到右逐个比较,步骤如下:
- 如果当前字符匹配成功,即S[i]==P[j],则i++,j++
- 如果当前字符匹配失败,则根据部分匹配表j的值来调整j的位置。具体地,设当前子串为S[i-k:i],部分匹配表为next[],则j=next[k]。
- 如果j=-1,则表示主串的当前位置i无法与模式串中任何位置匹配,此时i++,j++
需要注意的是,对于模式串的第一个字符,我们是不做比较,而是从第二个字符开始匹配。
根据部分匹配表调整匹配位置
在匹配失败时,我们需要根据部分匹配表来调整j的位置,具体地,设当前子串为S[i-k:i],部分匹配表为next[],则j=next[k]。需要注意的是,如果next[k]大于0,则部分匹配表的值本身就蕴含了“跳跃”的信息,即主串中不必从i-k这个位置开始逐个比较,而是可以直接跳到j=next[k]这个位置,从下一个字符开始比较。
Python代码实现示例
下面是一个简单的Python实现示例:
def kmp_search(s, p):
"""
KMP算法,用于字符串匹配
"""
m, n = len(s), len(p)
next = get_next(p)
i, j = 0, 0
while i<m and j<n:
if j==-1 or s[i]==p[j]:
i += 1
j += 1
else:
j = next[j]
if j == n:
return i - j
return -1
def get_next(p):
"""
构建部分匹配表
"""
n = len(p)
next = [-1] * n
i, j = 0, -1
while i<n-1:
if j==-1 or p[i]==p[j]:
i += 1
j += 1
next[i] = j
else:
j = next[j]
return next
下面是一个简单的例子,演示了如何在主串s中查找模式串p。
s = "BBC ABCDAB ABCDABCDABDE"
p = "ABCDABD"
pos = kmp_search(s, p)
if pos == -1:
print("Pattern not found in string.")
else:
print(f"Pattern found at position {pos}.")
示例说明
上述示例中,我们依次完成了以下操作:
- 首先定义了一个主函数kmp_search和一个辅助函数get_next。
- 在kmp_search函数中,我们首先使用get_next函数来生成部分匹配表,然后设置i,j的初值为0。
- 在while循环的过程中,我们依次比较s[i]和p[j],如果匹配成功,则继续下一组比较;如果匹配失败,则根据部分匹配表重新设置j的位置。
- 最后,如果j等于n,说明p已经完整匹配成功,返回i-j作为匹配位置;否则,返回-1表示匹配失败。
- 在最后一个代码块中,我们定义了一个主串s和一个模式串p,然后使用kmp_search函数来查找p在s中出现的位置,并将结果打印输出。
结论
KMP算法是一种高效的字符串匹配算法,相比于朴素的字符串匹配算法,它能够避免无谓的比较操作,减少了算法的时间复杂度。在实际应用中,KMP算法具有较为广泛的使用场景,如文本匹配、模式识别、音频处理等。掌握KMP算法的原理和实现方法,对于提高程序的效率和准确性具有非常重要的意义。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Python描述数据结构之KMP篇 - Python技术站