“KMP算法”中如何获取next[]数组:
以模式串T=“abaabcac”为例:
一、应对考试(要求写出T对应的next[]数组):(快速手算)
首先列出T的所有前缀(本身不是):
前缀 | 最大匹配数 |
---|---|
a | 0 |
ab | 0 |
aba | 1 |
abaa | 1 |
abaab | 2 |
abaabc | 0 |
abaabca | 1 |
T | a b a a b c a c |
---|---|
-1 0 0 1 1 2 0 1 | |
next[] | 0 1 1 2 2 3 1 2 |
过程:首先得到各个前缀的最大匹配数(0,0,1,1,2,0,1);然后在前面填个-1->(-1,0,0,1,1,2,0,1);next[]=(-1,0,0,1,1,2,0,1)+(1,1,1,1,1,1,1,1) = ( 0 1 1 2 2 3 1 2)
解释:例如如果在abaabc的最后一个c失配了,我们知道c前面的子串abaab的最大匹配数为2(匹配串为:ab);所以往后移动几位才能找到应该与主串失配位重新比较的位置呢?
我们知道往后移动2+1(失配位前面的子串的最大匹配数+1)个单位时,能满足要求。
二、适合写代码的方法:
(一)法只适合手算,代码不好实现
(二)法:
假设next[0]第一位闲置,用0填补,方便后续操作;
首先规定:next[1] = 0; next[2] = 1; (这是一定正确的)
当 i >.3时:假设在模式串的第 i 位置失配,如何计算next[i]呢?
令j = next[i-1]
首先比较 T[ j ] 和 T[ i-1 ] 是否相等,如果相等:next[ i ] = j +1;
如果不等:更新 j = next[ j ];
继续判断 T[ j ] 和 T[ i-1 ]是否相等。。。
如果 j =0 了,表示比较到了模式串的第一个字母了,所以此时:next[ i ] = 1;
填完 next[]数组 即结束。。。。。
Python实现:
def get_next(T):
global next
next = [0 for k in range(len(T))]
# 当len(T) == 1 or 2 or 3 时,next数组为默认值
if len(T)==1: # 注意:len(T)=len(模式串)+1
return next
if len(T)==2:
next[1] = 0
return next
if len(T)==3:
next[1], next[2] = 0, 1
return next
# 当len(T)>3时:
if len(T)>3:
next[1], next[2] = 0, 1
i = 3
j = next[i - 1] # 计算next[i]前对j的初始化
while i <= (len(T)-1):
if j == 0:
next[i] = 1
i += 1
j = next[i - 1]
continue
if T[i - 1] == T[j]: # T[i-1]为失配位置i的前一个位置的字母
next[i] = j + 1
i += 1
j = next[i - 1] # 计算next[i]前对j的初始化
else:
# 不满足相等的条件,则更新 j
j = next[j]
return next
pass
def main():
line = "abaabcac"
T = [0]+list(line) # 数组首位空置不用,用0填充
print(T)
next = get_next(T) # 获取next数组
print(next)
pass
main()