本文基于清华大学出版社1992年第二版《数据结构》(严蔚敏 吴伟民 编著)4.3.2节内容KMP算法,只是课本上伪代码的Python实现,没有对算法的详细解释。
匹配过程
伪代码
FUNC index_KMP(s,t:strtp):integer;
{利用模式串t中的next函数求模式串t在主串s中位置的KMP算法}
i:=1; j:=1; {下标初始化}
WHILE (i<=s.curlen) AND (j<=t.curlen) DO
IF (j=0) OR (s.ch[i]=t.ch[j])
THEN [ i:=i+1; j:=j+1 ] {继续下一对字符的比较}
ELSE j:=next[j]; {模式串向右滑动}
IF j>t.curlen THEN RETURN (i-t.curlen) {匹配成功}
ELSE RETURN(0)
ENDF; {index_KMP}
需要注意的是,伪代码中的下标是从1开始的,下文中的伪代码也是这样。因此,在Python代码中会有一些改动。
Python实现
def index(s, t):
i = 0
j = 0
while i < len(s) and j < len(t):
if j == -1 or s[i] == t[j]:
i += 1
j += 1
else:
j = next_j[j]
if j >= len(t):
return i - len(t)
else:
return -1
求next序列
伪代码
PROC get_next(t:strtp; VAR next:ARRAY[1…t.curlen] OF integer);
{求模式串t的next函数值并存入数组next}
j:=1; k:=0; next[1]=0; {初始化}
WHILE j<t.curlen DO
IF (k=0) OR (t.ch[j]=t.ch[k])
THEN [j:=j+1; k:=k+1; next[j]:=k]
ELSE k:=next[k]
ENDP; {get_next}
Python实现
j = 0
k = -1
next_j = [-1]
while j < len(t) - 1:
if k == -1 or t[j] == t[k]:
j += 1
k += 1
next_j.append(k)
else:
k = next_j[k]
完整代码
def index(s, t):
j = 0
k = -1
next_j = [-1]
while j < len(t) - 1:
if k == -1 or t[j] == t[k]:
j += 1
k += 1
next_j.append(k)
else:
k = next_j[k]
# 生成next序列
# print(next_j) # 检验next序列,输出为[-1, 0, 0, 1, 1, 2, 0, 1]
i = 0
j = 0
while i < len(s) and j < len(t):
if j == -1 or s[i] == t[j]:
i += 1
j += 1
else:
j = next_j[j]
if j >= len(t):
return i - len(t)
else:
return -1
# 模式匹配
str = 'acabaabaabcacaabc'
model = 'abaabcac'
print(index(str, model))
# 运行测试,输出为5