KMP算法 Next数组 3种主流实现对比:从-1/0版本到nextval优化详解
字符串匹配是计算机科学中最基础也最常用的操作之一,而KMP算法无疑是这个领域最优雅的解决方案。但当你真正动手实现时,会发现不同教材、不同代码库中Next数组的定义五花八门——有的从-1开始,有的从0开始,还有优化后的nextval版本。这些差异不仅让初学者困惑,甚至会导致实际编码时的隐蔽错误。本文将彻底拆解这三种主流实现,用可视化的匹配过程展示它们的行为差异,并给出不同场景下的选择建议。
1. Next数组的本质与三种变体
Next数组是KMP算法的灵魂所在,它记录了模式串自身的结构信息。简单来说,Next[j]表示当模式串第j个字符匹配失败时,应该回退到哪个位置继续匹配。但就是这个看似简单的定义,在实际实现中却衍生出多个版本:
1.1 经典-1版本
这是最接近KMP原始论文的实现方式,Next[0]固定为-1。以模式串"ababac"为例:
# -1版本Next数组计算
def build_next(p):
next = [-1] * len(p)
j, k = 0, -1
while j < len(p) - 1:
if k == -1 or p[j] == p[k]:
j += 1
k += 1
next[j] = k
else:
k = next[k]
return next
print(build_next("ababac")) # 输出: [-1, 0, 0, 1, 2, 3]
这个版本的特性是:
- 边界处理 :当k=-1时表示需要移动模式串整体
- 直观性 :Next值直接对应字符索引
- 匹配逻辑 :失配时j = Next[j]
1.2 零起始版本
许多现代教材采用的实现方式,Next[0]=0:
# 0版本Next数组计算
def build_next_zero(p):
next = [0] * len(p)
j, k = 1, 0
while j < len(p):
if k == 0 or p[j-1] == p[k-1]:
next[j] = k
j += 1
k += 1
else:
k = next[k]
return next
print(build_next_zero("ababac")) # 输出: [0, 0, 1, 2, 3, 0]
关键差异:
- 索引偏移 :N


2万+

被折叠的 条评论
为什么被折叠?



