模式串和主串进行比较,当主串的第 i 个字符和模式串的第 j 个字符比较不同时,i 不用动,j 向前滑动到 k 即可。
当务之急是是找到,最大的 k,使得 pattern[0: k] == pattern[j-1-k: j-1],那么当匹配失败时,模式串 j 重置为 k 继续比较即可。
同时要注意,k < j,next[0] = -1(当第一个不匹配,特殊行为,i++, j++)
def get_next(pattn):
"""
获取模式串的 next 数组,和平常所见处理不同,多一
next[i] < i
当模式串第 j 个字符和主串第 i 个字符不匹配时:
1. 若 next[j] == -1, i += 1, j += 1
2. 否则 j = next[j] 继续比较
"""
N = len(pattn)
next_i = [0 for _ in range(N)]
# 当字符 0 不匹配,行为特殊,需要 i++ j++
# 只要字符 1 不匹配,都得从字符 0 开始比较
next_i[0:2] = [-1, 0]
k = 0
i = 2
while(i < N):
# 找出最大的 k (k<i) 使得 pattn[0:k-1] == pattn[i-k:i-1]
if k == -1:
# 3. 说明已经比较到了 pattn[0] != pattn[i-1]
# 即没有相等的
# 分支能够合并,但为了思路清晰,分开写
k += 1 # 将 k 重置为 0
next_i[i] = 0
i += 1
continue
if pattn[k] == pattn[i-1]:
# 1.
k += 1
next_i[i] = k
i += 1
else:
# 2. 这其实也是一个模式串匹配的问题
# 模式串 pattn[0:k],主串 pattn[i-k:i-1]
# 当匹配失败时,模式串跳转到 next[k] 即可
k = next_i[k]
return next_i