“给定文本 $T$ 和非空模式 $P$,令 $m= P $,先计算模式的 前缀函数 $\pi$。扫描文本时维护状态 $q$:已经读过的文本前缀中,最长且等于 $P[0..q 1]$ 的后缀长度…”
形式陈述 ​
给定长度为
也就是说,
整个数组可由下列回退过程在线性时间求出:
π[0] = 0
for i = 1, 2, ..., n - 1:
j = π[i - 1]
while j > 0 and s[i] != s[j]:
j = π[j - 1]
if s[i] == s[j]:
j = j + 1
π[i] = j
若字符串为空,前缀函数就是空数组;实现时应把这一接口情形置于循环之外处理。
直觉
一个 border 是同时出现在字符串两端的同一段内容。已知
如果这两个字符失配,并不需要把候选降到零。任何仍可能延长的候选,必须既是
会按长度从大到小枚举全部可行 border,而不会漏掉中间候选。这个“最长 border 的最长 border”链,就是前缀函数压缩重复结构的方式。
算法结束一轮时维持如下不变量:while 中每次回退都会严格减小
例子与边界
字符串 aabaaab 的前缀函数为
前五个字符 aabaa 的最长 border 是 aa,所以 a 时,长度 b,发生失配;回退到 a 延长,于是 b 时,aa 可延长为 aab,得到
前缀函数保存的是长度,不是字符下标。候选长度为 0 同时表示空 border 和没有更短候选,不代表首字符已经匹配。
若要列出整个字符串长度
推论与应用
词与序列给出离散对象,前缀函数则为每个前缀组织 border 链。KMP把这条链用作模式失配后的状态回退;本条只负责解释
前缀出现次数也能由同一棵失败链汇总。先把每个位置贡献给其 # 和文本 P#T,则拼接串上值等于
前缀函数与Z 函数都编码字符串前缀与其他位置的重合信息,并可在线性时间互相转换;equivalent_to 指的是信息层面的可恢复性,不表示两个数组逐项相等,也不表示两套更新公式可以混用。若预处理对象从单个模式改成固定全文,则应转向 FM-index 等全文索引;那是查询模型的改变,而不是前缀函数的另一种写法。
参考资料
- Donald E. Knuth, James H. Morris Jr., and Vaughan R. Pratt, “Fast Pattern Matching in Strings,” SIAM Journal on Computing 6(2), 1977, pp. 323–350.
- Dan Gusfield, Algorithms on Strings, Trees, and Sequences, Cambridge University Press, 1997, Ch. 1.
- cp-algorithms contributors, “Prefix Function,” Algorithms for Competitive Programming, accessed August 9, 2026.