Skip to content

前缀函数

Prefix function · Failure function

记录每个前缀的最长真前缀—后缀重合长度的字符串函数。

条目类型
定义

形式陈述

给定长度为 n 的字符串 s=s[0]s[1]s[n1],前缀函数在位置 i 的值定义为

π[i]=max({0}{k:1k<i+1, s[0..k1]=s[ik+1..i]}).

也就是说,π[i] 是前缀 s[0..i] 的最长真前缀与后缀的共同长度。这里“真”排除了整个 s[0..i],所以总有 0π[i]i,并且 π[0]=0

整个数组可由下列回退过程在线性时间求出:

text
π[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 是同时出现在字符串两端的同一段内容。已知 s[0..i1] 的最长 border 长度为 j 时,加入新字符 s[i],最乐观的候选只是把原 border 延长一位:比较 s[i]s[j]。候选不可能一次增长两位,因为删掉新字符后就会得到一个比 j 更长的旧 border,与 j=π[i1] 矛盾。

如果这两个字符失配,并不需要把候选降到零。任何仍可能延长的候选,必须既是 s[0..j1] 的真 border,又是当前前缀的后缀;其中最长者正是 π[j1]。于是反复执行

jπ[j1]

会按长度从大到小枚举全部可行 border,而不会漏掉中间候选。这个“最长 border 的最长 border”链,就是前缀函数压缩重复结构的方式。

算法结束一轮时维持如下不变量:j 是能与 s[i] 相容的最长旧 border,若字符相等则延长为 j+1,否则在 j=0 时得到零。正确性来自候选链的完备性;线性复杂度则来自候选长度的单调记账。外层每前进一步,j 最多增加 1while 中每次回退都会严格减小 j,总下降量不可能超过此前的总上升量。再计入每个位置常数次比较,时间为 O(n),空间为存储数组所需的 O(n)

border、失配回退与前缀函数值
例子与边界

字符串 aabaaab 的前缀函数为

[0,1,0,1,2,2,3].

前五个字符 aabaa 的最长 border 是 aa,所以 π[4]=2。处理位置 5 的字符 a 时,长度 2 的候选期待下一个字符为 b,发生失配;回退到 π[1]=1 后,长度 1 的 border 可以用 a 延长,于是 π[5]=2。这里新值仍为 2,但它来自较短 border 的重新延长,而不是保留了已经失配的候选。处理最后的 b 时,aa 可延长为 aab,得到 π[6]=3

前缀函数保存的是长度,不是字符下标。候选长度为 j 时,下一个待比较字符是 s[j];回退目标是 π[j1]。把它误写成 π[j],既混淆长度与下标,也可能无法严格缩短候选而陷入循环。0 同时表示空 border 和没有更短候选,不代表首字符已经匹配。

若要列出整个字符串长度 n 的所有非空 border,先取 k=π[n1],再依次取 k=π[k1],直到零。每个 border 长度 k 都给出一个周期候选 nk;但只有当 n 能被 nk 整除时,字符串才是该长度块的整数次幂。把“存在周期”与“恰由一个块重复组成”混为一谈,会产生错误的周期判断。

推论与应用

序列给出离散对象,前缀函数则为每个前缀组织 border 链。KMP把这条链用作模式失配后的状态回退;本条只负责解释 π 的定义、构造和结构性质,文本扫描与匹配报告由 KMP 条目承担。

前缀出现次数也能由同一棵失败链汇总。先把每个位置贡献给其 π[i],再按长度从大到小把计数累加给 π[k1],就会把较长前缀的每次出现传给它的所有 border;最后还要为每个非空前缀计入它作为自身出现的那一次。若将模式 P、一个不在字母表中的分隔符 # 和文本 T 拼成 P#T,则拼接串上值等于 |P| 的位置恰对应完整匹配;分隔符不可省略,否则 border 可能跨越模式与文本的边界。

前缀函数与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.
关系图谱6 个相邻概念 · 3 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系

被这些条目使用

限定层次等价