KMP算法中的next数组实现
KMP算法的核心在于预处理模式串生成next数组,用于匹配失败时快速跳转。next[i]表示模式串P[0..i-1]的最长公共前后缀长度(不包括整个子串本身)。
数学定义
设模式串为$P$,长度为$m$:
- $next[0] = -1$(空串无前后缀)
- 对于$i > 0$,$next[i] = \max{k \mid 0 \leq k < i,\ P[0..k-1] = P[i-k..i-1]}$
生成逻辑(手写代码)
def build_next(pattern: str) -> list:
m = len(pattern)
next_arr = [-1] * m # 初始化数组
i, j = 0, -1 # i: 当前下标, j: 前缀指针
while i < m - 1: # 注意只需遍历到 m-2
# 字符匹配成功时扩展前缀
if j == -1 or pattern[i] == pattern[j]:
i += 1
j += 1
next_arr[i] = j # 记录最长公共前后缀长度
# 失配时回退前缀指针
else:
j = next_arr[j]
return next_arr
关键步骤解析
-
初始化:
next_arr[0] = -1(固定值)- 双指针
i=0(主指针),j=-1(前缀指针)
-
循环处理($i$从$0$到$m-2$):
- 匹配成功($P[i] = P[j]$):
- 同时移动$i$和$j$
- 设置$next[i] = j$(当前最长公共长度)
- 匹配失败($P[i] \neq P[j]$):
- 利用已计算的$next$值回退:$j = next[j]$
- 当$j=-1$时强制移动$i$
- 匹配成功($P[i] = P[j]$):
-
终止条件:
- $i$达到$m-1$时停止($next$最后一个值由倒数第二位置推导)
示例演示
以模式串"ababc"为例:
步骤 i j P[i] P[j] 操作 next数组
初始化 0 -1 'a' N/A → i=1,j=0 [-1, 0, -1, -1, -1]
1 1 0 'b' 'a' 失配 j=next[0]=-1
2 1 -1 'b' N/A → i=2,j=0 [-1, -1, 0, -1, -1]
3 2 0 'a' 'a' 匹配 → i=3,j=1 [-1, -1, 0, 1, -1]
4 3 1 'b' 'b' 匹配 → i=4,j=2 [-1, -1, 0, 1, 2]
5 4 2 'c' 'a' 失配 j=next[2]=0
6 4 0 'c' 'a' 失配 j=next[0]=-1
7 4 -1 'c' N/A 终止
最终next = [-1, -1, 0, 1, 2]
特性说明
- 时间复杂度:$O(m)$(每个字符最多比较两次)
- 空间复杂度:$O(m)$
- 跳转原理:当$P[i]$匹配失败时,直接跳转到$P[next[i]]$继续匹配,避免回溯主串
此实现符合KMP原始论文规范,实际使用时需注意不同文献中$next$数组起始下标可能不同(有0-based和1-based两种常见形式)。
1136

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



