Skip to content

定义Definition

前缀函数

Prefix function · Failure function

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

形式陈述 ​

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

π[i]=max({0}∪{k:1≤k<i+1, s[0..k−1]=s[i−k+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..i−1] 的最长 border 长度为 j 时,加入新字符 s[i],最乐观的候选只是把原 border 延长一位:比较 s[i] 与 s[j]。候选不可能一次增长两位,因为删掉新字符后就会得到一个比 j 更长的旧 border,与 j=π[i−1] 矛盾。

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

j←π[j−1]

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

每轮的 while 沿候选链排除无法延长的 border,直到找到最长可延长候选,或退回长度零。随后的字符比较把候选延长一位;若长度零仍失配,就令 π[i]=0。候选链的完备性保证这就是最长的新 border。

线性复杂度来自候选长度的记账:外层每前进一步,j 最多增加 1;while 中每次回退都会严格减小 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];回退目标是 π[j−1]。把它误写成 π[j],既混淆长度与下标,也可能无法严格缩短候选而陷入循环。0 同时表示空 border 和没有更短候选,不代表首字符已经匹配。

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

推论与应用

词与序列给出离散对象,前缀函数则为每个前缀组织 border 链。KMP把这条链用作模式失配后的状态回退。

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

前缀函数与Z 函数都编码字符串前缀与其他位置的重合信息,可在线性时间互相恢复;它们记录的长度含义不同,各有相应的构造算法。若要对固定全文回答许多模式查询,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.
  • Frantisek Franek, W. F. Smyth and Xinfang Wang, “The Role of the Prefix Array in Sequence Analysis: A Survey”, 2017,讨论 border array 与 prefix array 的线性互换;该文的 prefix array 指本库的 Z 数组。
  • cp-algorithms contributors, “Prefix Function,” Algorithms for Competitive Programming, accessed August 9, 2026.
关系图谱7 个相邻概念 · 3 类关系

拖动节点调整位置。

显示关系

显示:依赖

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

被这些条目使用

限定层次等价