KMP算法
简介
一种用于字符串匹配的快速算法。该算法的核心在于利用已经匹配过的信息,避免不必要的字符比较,从而提高匹配效率。其中的一个关键部分是计算next数组,它用于指示在匹配失败时,应该将模式串向右移动多少位。
关键的next 数组怎么计算的?
下面是计算next数组的基本步骤:
-
初始化:将next数组的第一个元素(next[0])设为-1,将next数组的第二个元素(next[1])设为0。
-
遍历模式串:从模式串的第二个字符(下标为1)开始,依次计算每个位置上的next值。
-
计算next值:
对于位置i,从i-1位置开始向前找,找到第一个与模式串第i个字符相等的位置j。然后,next[i]的值为j+1。
-
如果找不到这样的j,说明在当前位置i匹配失败时,应该将模式串整体向右移动一位,即next[i]为0。
如果找到了j,说明在当前位置i匹配失败时,可以利用已匹配的信息,将模式串右移j+1位。
重复:继续遍历模式串的下一个位置,重复步骤3,直到计算完整个next数组。
下面是一个示例,说明如何计算next数组:
"ABABCD"
初始化:将next数组的第一个元素(next[0])设为-1,将next数组的第二个元素(next[1])设为0。
A B A B C D
-1 0
对于位置1(B),[没找到与B相同的],所以 next[2] = 0 。
A B A B C D
-1 0 0
对于位置2(A),找到位置0(A),所以 next[3] = 0+1=1。
A B A B C D
-1 0 0 1
对于位置3(B),找到位置1(B),所以 next[4] = 1+1=2。
A B A B C D
-1 0 0 1 2
对于位置4(C),没找到相同的,所以 next[5] = 0。
A B A B C D
-1 0 0 1 2 0
def compute_next(pattern):
"""
计算模式串的next数组
"""
m = len(pattern)
next_array = [-1] * m
j = -1
for i in range(1, m):
while j >= 0 and pattern[i - 1] != pattern[j]: # 没有走到 -1 就是数组的头部,且不相等
j = next_array[j]
j += 1
next_array[i] = j
return next_array
def kmp_search(text, pattern):
"""
KMP算法进行字符串匹配
"""
n = len(text)
m = len(pattern)
next_array = compute_next(pattern)
print("next数组:",next_array)
i = j = 0
while i < n: # 匹配是否到text末尾
while j >= 0 and text[i] != pattern[j]: #
j = next_array[j]
i += 1
j += 1
if j == m:
# 匹配成功,返回匹配位置的起始索引
return i - j
# 没有匹配成功,返回-1
return -1
# 测试
text = "ABABCABABCABCABABCD"
pattern = "ABABCD"
result = kmp_search(text, pattern)
if result != -1:
print(f"在文本中找到模式串,起始位置为:{result}")
else:
print("在文本中未找到模式串")