跳转至

字符串算法

方法速览

任务 方法 口诀
next 手算 next[i] = 前缀 P[0..i] 的最长相等真前后缀 掐头去尾对齐
失配移动 模式串滑到 next 位置续比,文本指针不动 文本不回头
最短循环节 长度 n、next[n−1] = d,且 (n−d) 整除 n → 循环节长 n−d 减去 next
子串哈希 前缀哈希差分取子串值,O(1) 比较 前缀差分
Trie 结点数 = 互异前缀 + 根;查前缀走 m 步 数前缀加根

KMP 的 next 数组

【是什么】 next[i] = 子串 P[0..i]最长相等真前后缀长度(真 = 不含整个串)。

【怎么算】 对每个位置,找掐掉首尾后能与开头对齐的最长长度。

【例】(2025 真题)P = "abacaba"

i 0 1 2 3 4 5 6
P[i] a b a c a b a
next 0 0 1 0 1 2 3

逐位解释:aba 首 a = 尾 a(1);abacab 前缀 ab = 后缀 ab(2);abacaba 前缀 aba = 后缀 aba(3)。

【失配移动】 匹配到 P[j] 失配时,模式串右滑、用 next[j-1] 位置的字符继续比较——已匹配前缀的后缀与模式串前缀相等,这段不用重比;文本指针全程不回退,总复杂度 \(O(n+m)\)

循环节

【是什么】 串 S 由长度 L 的块重复若干次构成,L 最小者为最短循环节。

【怎么算】 \(L = n - next[n-1]\);当 \(L \mid n\) 时整串恰由整数个块组成。

【例】 abcabcabc(n = 9):next[8] = 6,\(L = 9 - 6 = 3\),3 整除 9 → 循环节 abc

字符串哈希与 Trie

  • 哈希:把前缀 S[0..i] 映射成多项式值 \(h_i\),子串 S[l..r] 的哈希 = \(h_r - h_{l-1}\cdot B^{r-l+1}\)——O(1) 取值、O(1) 比子串相等;单哈希可能碰撞,双哈希(两组底数与模数)把冲突压到可忽略;
  • Trie:结点数 = 所有串的互异前缀数 + 1(根);查某前缀是否存在沿边走 m 步;判“是否为已存串的前缀”是 Trie 的本职。

练习题目

练习 1 · next 定义

题目

KMP 中 next[i] 的定义是( )

  • A. P[0..i] 的长度
  • B. P[0..i] 的最长相等真前后缀长度
  • C. 失配次数
  • D. 字符的 ASCII 值
答案与解析

答案:B

“真”表示不能取整个串本身。

练习 2 · next 手算(aab)

题目

P = "aab" 的 next 数组是( )

  • A. {0, 0, 1}
  • B. {0, 1, 1}
  • C. {0, 1, 0}
  • D. {1, 1, 0}
答案与解析

答案:C

a=0;aa 前后缀 a=a(1);aab 无相等前后缀(0)。

练习 3 · next 手算(周期串)

题目

P = "aaaa" 的 next 数组是( )

  • A. {0, 0, 0, 0}
  • B. {1, 2, 3, 4}
  • C. {0, 1, 1, 1}
  • D. {0, 1, 2, 3}
答案与解析

答案:D

前缀长 1、2、3 的 a 串都能与后缀对齐——全同一字符逐位加一。

练习 4 · next 手算(abab)

题目

P = "abab" 的 next 数组是( )

  • A. {0, 0, 1, 2}
  • B. {0, 0, 1, 0}
  • C. {0, 1, 1, 2}
  • D. {0, 0, 0, 2}
答案与解析

答案:A

aba(1);abab 前后 ab(2)——隔位上涨是 ab 交替串的形状。

练习 5 · next 手算(abcab)

题目

P = "abcab" 的 next 数组是( )

  • A. {0, 0, 0, 0, 1}
  • B. {0, 0, 0, 1, 2}
  • C. {0, 1, 1, 1, 2}
  • D. {0, 0, 0, 1, 0}
答案与解析

答案:B

abca 首 a = 尾 a(1);abcabab = 后 ab(2)。

练习 6 · next 手算(abcabd)

题目

P = "abcabd" 的 next 数组是( )

  • A. {0, 0, 0, 1, 2, 3}
  • B. {0, 0, 0, 0, 1, 2}
  • C. {0, 0, 0, 1, 2, 0}
  • D. {0, 1, 0, 1, 2, 0}
答案与解析

答案:C

abcab 时 next = 2;末位 d 与前缀 ab 后继 c 不匹配,跌回 0。

练习 7 · next 手算(aabaab)

题目

P = "aabaab" 的 next 数组是( )

  • A. {0, 1, 0, 1, 2, 0}
  • B. {0, 0, 0, 1, 2, 3}
  • C. {0, 1, 1, 1, 2, 3}
  • D. {0, 1, 0, 1, 2, 3}
答案与解析

答案:D

aab:前后缀 a(1);aabaab 前后 aab(3)——小循环节串的 next 呈周期跳。

练习 8 · 失配跳转

题目

KMP 失配时下一步用 next 做什么( )

  • A. 模式串滑到 next[失配位前一位] 对应位置继续比,文本指针不动
  • B. 文本回退到开头
  • C. 重新从头比
  • D. 报错
答案与解析

答案:A

已匹配前缀的后缀信息复用——文本指针不回退是 \(O(n+m)\) 的关键。

练习 9 · KMP 复杂度

题目

KMP 匹配的总时间复杂度( )

  • A. \(O(nm)\)
  • B. \(O(n + m)\)
  • C. \(O(n\log m)\)
  • D. \(O(n^2)\)
答案与解析

答案:B

两个指针都只前进不回退(均摊分析);\(O(nm)\) 是朴素逐位重比。

练习 10 · 朴素匹配最坏

题目

朴素(暴力)字符串匹配的最坏时间复杂度( )

  • A. \(O(n + m)\)
  • B. \(O(n\log n)\)
  • C. \(O(nm)\)
  • D. \(O(n)\)
答案与解析

答案:C

每个起点都可能比满 m 位(如 aaaaabaab 型)——KMP 正是治这个的。

练习 11 · 最长相等真前后缀

题目

abcabc 的最长相等真前后缀长度是( )

  • A. \(6\)
  • B. \(0\)
  • C. \(2\)
  • D. \(3\)
答案与解析

答案:D

abc = 后 abc;6 是整个串不算“真”。

练习 12 · 循环节(整除)

题目

abcabcabc 的最短循环节长度是( )

  • A. \(3\)
  • B. \(9\)
  • C. \(6\)
  • D. \(1\)
答案与解析

答案:A

\(n - next[n-1] = 9 - 6 = 3\),且 3 整除 9。

练习 13 · 循环节(不整除)

题目

长度 9、next[8] = 5 的串,\(n - next[n-1] = 4\) 不整除 9,说明( )

  • A. 循环节是 9
  • B. 整串不是周期串(4 只是“近似周期”)
  • C. 无意义
  • D. 串长必为 8
答案与解析

答案:B

只有 \(L = n - next[n-1]\) 整除 n 时才构成完整周期;否则只是前后缀的重叠。

练习 14 · 子串哈希

题目

字符串哈希把子串比较转化为( )

  • A. 逐字符比较
  • B. 排序
  • C. 数值(前缀哈希差分)比较,O(1)
  • D. 二分
答案与解析

答案:C

预处理前缀哈希后 O(1) 取任意子串哈希值。

练习 15 · 双哈希

题目

实战中用两组底数和模数做双哈希的目的是( )

  • A. 加快一倍
  • B. 节省内存
  • C. 支持修改
  • D. 降低哈希碰撞概率
答案与解析

答案:D

两组哈希同时碰撞才会误判——概率乘起来可忽略。

练习 16 · 哈希相等

题目

两个子串哈希值相等(单哈希)说明( )

  • A. 极大概率相等,但不保证
  • B. 一定相等
  • C. 一定不等
  • D. 无信息
答案与解析

答案:A

哈希是压缩映射,不同串可能同值(碰撞);双哈希或直接比对兜底。

练习 17 · Trie 结点数

题目

heshe 插入空 Trie(含根),结点总数是( )

  • A. \(5\)
  • B. \(6\)
  • C. \(4\)
  • D. \(7\)
答案与解析

答案:B

互异前缀 h、he、s、sh、she 共 5,加根 = 6。

练习 18 · Trie 查找复杂度

题目

在 Trie 中查找一个长度为 m 的串,时间复杂度( )

  • A. \(O(m \log \sigma)\)
  • B. \(O(\text{串总数})\)
  • C. \(O(m)\)
  • D. \(O(m^2)\)
答案与解析

答案:C

每字符沿边走一步、共 m 步——与库里存了多少串无关。

练习 19 · Trie 判前缀

题目

判断某串是否为已有串的前缀,最适合( )

  • A. 快速排序
  • B. 并查集
  • C. 堆
  • D. Trie
答案与解析

答案:D

沿边走 m 步即知——Trie 天生存前缀。

练习 20 · Manacher

题目

Manacher 算法解决( )问题,复杂度( )

  • A. 最长回文子串,\(O(n)\)
  • B. 最长公共子序列,\(O(n\log n)\)
  • C. 字符串匹配,\(O(n+m)\)
  • D. 排序,\(O(n^2)\)
答案与解析

答案:A

利用已求回文的对称性线性扩展回文半径。

练习 21 · 回文判断

题目

下列是回文串的是( )

  • A. abcab
  • B. abcba
  • C. aabbc
  • D. abcabc
答案与解析

答案:B

正读反读相同——双指针从两端向中间比对。

练习 22 · 子串计数

题目

长度为 n 的串按位置数的子串共( )个。

  • A. \(2^n\)
  • B. \(n^2\)
  • C. \(\dfrac{n(n+1)}{2}\)
  • D. \(n - 1\)
答案与解析

答案:C

起点终点各选一层求和;\(2^n\) 是子序列数。

练习 23 · 本质不同子串

题目

aaa 的本质不同子串有( )个。

  • A. \(6\)
  • B. \(1\)
  • C. \(2\)
  • D. \(3\)
答案与解析

答案:D

内容只有 aaaaaa 三种——按位置 6 个、按内容 3 个。

练习 24 · 子串 vs 子序列

题目

ac 对于 abc 是( )

  • A. 子序列但不是子串
  • B. 子串但不是子序列
  • C. 都是
  • D. 都不是
答案与解析

答案:A

保序跳选是子序列;不连续不是子串。

练习 25 · LCS 的解法

题目

最长公共子序列(LCS)的正确解法是( )

  • A. 贪心取公共字符
  • B. 二维 DP
  • C. 排序后比对
  • D. KMP
答案与解析

答案:B

失配时左/上两种取舍需要全子问题表——贪心不成立(KMP 管匹配不管公共子序列)。

练习 26 · 综合判断

题目

下列错误的是( )

  • A. next 数组是模式串自身的性质
  • B. Trie 的结点数等于互异前缀数加一
  • C. KMP 最坏 \(O(nm)\)
  • D. 子串哈希可 O(1) 比较子串相等
答案与解析

答案:C

KMP 最坏也是 \(O(n+m)\)\(O(nm)\) 是朴素匹配。

历年真题

2025 年 · 第 2 题

题目

KMP 算法中,对于模式串 P="abacaba",其 next 数组(next[i] 定义为模式串 P[0...i] 最长公共前后缀的长度,且数组下标从 \(0\) 开始)的值是什么?

  • A. {0, 0, 1, 0, 1, 2, 3}
  • B. {0, 1, 2, 3, 4, 5, 6}
  • C. {0, 0, 1, 1, 2, 2, 3}
  • D. {0, 0, 0, 0, 1, 2, 3}
答案与解析

答案:A

逐位求最长相等真前后缀(完整表格见教学节):a0、ab0、aba1、abac0、abaca1、abacab2、abacaba3。

易错小结

  • next 是模式串自身的最长相等真前后缀(2025 真题 {0,0,1,0,1,2,3});全同串逐位 +1、ab 交替隔位涨;
  • 失配跳 next、文本指针不回退 → KMP \(O(n+m)\);朴素匹配最坏才 \(O(nm)\)
  • 最短循环节 \(n - next[n-1]\)整除 n 才是真周期;
  • 子串哈希 O(1) 比较、双哈希防碰撞;Trie 结点 = 互异前缀 + 根;
  • 子串(连续)与子序列(保序跳选)区分;LCS 是二维 DP,不是 KMP 也不是贪心。