先复习一下朴素串匹配算法:
#朴素串匹配算法
def navie_matching(t, p):
m, n = len(p), len(t)
i, j = 0, 0
while i < m and j < n: # i == m 说明找到匹配
if p[i] == t[j]: # 字符相同, 考虑下一对字符
i, j = i + 1, j + 1
else: # 字符不同, 考虑t中下一个位置
i, j = 0, j - i + 1
if i == m:
return j - i
return -1
时间复杂度为 O(m * n)
KMP算法:
根据模式串做出pnext表,实现无回溯串匹配
# KMP算法(无回溯串匹配算法)
def matching_KMP(t, p , pnext):
""""KMP串匹配, 主函数."""
j, i = 0, 0
n, m = len(t), len(p)
while j < n and i < m:
if i == -1 or t[j] == p[i]: # 考虑p中下一字符
j, i = j + 1, i + 1
else: # 考虑pnext决定下一个字符串
i = pnext[i]
if i == m:
return j-i
return -1
def gen_pnext(p):
"""生成针对p中各位置i的下一检查位置表,用于KMP算法"""
i, k, m = 0, -1, len(p)
pnext = [-1] * m # 初始数组元素全为1
while i < m-1: # 生成下一个pnext元素值
if k == -1 or p[i] == p[k]:
i, k = i+1, k+1
pnext[i] = k # 设置pnext元素
else:
k = pnext[k] # 退到更短相同前缀
return pnext
def gen_pnext(p):
"""生成针对p中各位置i的下一检查位置表,用于KMP算法,优化版本"""
i, k, m = 0, -1, len(p)
pnext = [-1] * m
while i < m-1:
if k == -1 or p[i] == p[k]:
i, k = i+1, k+1
if p[i] == p[k]:
pnext[i] = pnext[k]
else:
pnext[i] = k
else:
k = pnext[k]
return pnext
时间复杂度为 O(m + n)