mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6mobile wallpaper 7mobile wallpaper 8mobile wallpaper 9mobile wallpaper 10mobile wallpaper 11mobile wallpaper 12mobile wallpaper 13
13327 字
35 分鐘
字符串算法
2026-06-03

第 9 章 字符串算法#

本章目标:掌握从暴力匹配到 KMP、Trie、字符串哈希、Manacher 和 AC 自动机的基本思想。


9.1 学习目标#

  1. 理解字符串匹配的核心问题。
  2. 掌握 KMP 前缀函数。
  3. 掌握 Trie 的插入和查询。
  4. 掌握字符串哈希的前缀形式。
  5. 了解 Manacher 和 AC 自动机适用场景。

9.2 字符串匹配问题#

给定文本 T 和模式 P,找 P 在 T 中出现的位置。

暴力匹配复杂度:

O(TP)O(|T|\cdot |P|)

KMP 可以优化到:

O(T+P)O(|T|+|P|)

9.3 KMP 与前缀函数#

前缀函数 π[i]\pi[i] 表示字符串 s[0..i]s[0..i] 的最长相等真前后缀长度。

例如:

s = ababa
pi = 0 0 1 2 3

计算过程:

vector<int> prefix_function(string s) {
int n = s.size();
vector<int> pi(n);
for (int i = 1; i < n; i++) {
int j = pi[i - 1];
while (j > 0 && s[i] != s[j]) j = pi[j - 1];
if (s[i] == s[j]) j++;
pi[i] = j;
}
return pi;
}

失配时跳到 π[j1]\pi[j-1],因为这个长度仍可能继续匹配。


9.4 Trie 字典树#

Trie 用路径表示字符串。

适用场景:

  1. 前缀查询。
  2. 字典集合。
  3. 单词自动补全。
  4. 最大异或对。

插入:

void insert(string s) {
int u = 0;
for (char c : s) {
int x = c - 'a';
if (!tr[u][x]) tr[u][x] = ++idx;
u = tr[u][x];
}
end[u]++;
}

空间复杂度约为所有字符串长度总和乘字符集大小。


9.5 字符串哈希#

多项式哈希:

H(s)=i=0n1val(si)pimodMH(s)=\sum_{i=0}^{n-1} val(s_i) p^i \bmod M

更常用前缀写法:

h[i+1]=h[i]p+val(si)h[i+1]=h[i]\cdot p + val(s_i)

子串 [l,r)[l,r) 哈希:

H(l,r)=h[r]h[l]prlH(l,r)=h[r]-h[l]\cdot p^{r-l}

哈希可用于:

  • 子串比较。
  • 最长重复子串。
  • 回文判断。
  • 字符串去重。

9.6 Manacher#

Manacher 在线性时间求每个中心的最长回文半径。

核心技巧:

  1. 在字符间插入特殊符号,统一奇偶回文。
  2. 维护当前最右回文区间。
  3. 利用对称位置的半径减少重复扩展。

复杂度:O(n)O(n)


9.7 AC 自动机#

AC 自动机用于多模式串匹配。它把 Trie 和 KMP 的 fail 指针结合起来。

用途:

  • 敏感词匹配。
  • 多关键词检索。
  • 字符串 DP。

构建思路:

  1. 把所有模式串插入 Trie。
  2. BFS 建立 fail 指针。
  3. 扫描文本时按自动机转移。

9.8 易错点#

  1. KMP 中 j 回退写成 j—,退化成暴力。
  2. Trie 节点数组没初始化。
  3. 哈希取模后出现负数。
  4. 单哈希碰撞导致误判。
  5. Manacher 插入分隔符后下标换算错误。
  6. AC 自动机 fail 指针没有 BFS 构建。

9.9 练习#

  1. 用 KMP 找模式串所有出现位置。
  2. 用 Trie 实现单词插入和前缀查询。
  3. 用字符串哈希判断两个子串是否相等。
  4. 用 Manacher 求最长回文子串。
  5. 用 AC 自动机统计多个模式串出现次数。

ACM/OI 扩展:ACM 字符串模板补充#

本节补充 OIer 和 ACMer 常用的算法套路、模板、复杂度分析和易错点。 写模板时默认使用 C++17,变量名尽量短,但注释要说明不变量和适用条件。

1. KMP 模板#

前缀函数是最常用的 KMP 写法。

vector<int> prefix_function(const string& s) {
int n = (int)s.size();
vector<int> pi(n);
for (int i = 1; i < n; ++i) {
int j = pi[i - 1];
while (j > 0 && s[i] != s[j]) j = pi[j - 1];
if (s[i] == s[j]) ++j;
pi[i] = j;
}
return pi;
}

要点

  • 匹配可对 pattern + # + text 求前缀函数。
  • # 必须是不在字符集中的分隔符。

2. Z 函数#

Z[i] 表示 s[i..] 与 s 的最长公共前缀长度。

vector<int> z_function(const string& s) {
int n = s.size();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r) z[i] = min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i];
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
}
return z;
}

要点

  • Z 函数也能做模式匹配。
  • 比 KMP 在某些前缀匹配统计中更直观。

3. 双哈希#

降低字符串哈希碰撞概率。

const long long mod1 = 1000000007, mod2 = 1000000009, base = 911382323;
struct H { long long x, y; };
bool operator==(const H& a, const H& b) { return a.x == b.x && a.y == b.y; }

要点

  • base 可随机选择。
  • 自然溢出 unsigned long long 也常用。

4. 后缀数组用途#

后缀数组按字典序排列所有后缀,LCP 表示相邻后缀最长公共前缀。

要点

  • 不同子串数量:n(n+1)/2LCPn(n+1)/2 - \sum LCP
  • 最长重复子串:max LCP。
  • 多个串公共子串:拼接后结合来源和 LCP。

5. AC 自动机应用#

多模式匹配和敏感词过滤常用。

要点

  • Trie 边表示字符转移。
  • fail 指针表示当前匹配失败后最长可用后缀。
  • BFS 建 fail。
  • 扫描文本时按自动机转移并累计终止标记。

训练题型

  • 多模式串出现次数。
  • 禁止模式串的字符串计数 DP。

本章模板背诵清单#

  • 能在 5 分钟内写出本章第一个核心模板。
  • 能说出每个模板的时间复杂度和空间复杂度。
  • 能说明模板不适用的反例。
  • 能为模板构造 3 个边界样例。
  • 能把模板改成 0-index 或 1-index 版本。

字符串进阶补充#

Manacher 模板#

线性时间求所有回文半径。

vector<int> manacher(string s) {
string t = "#";
for (char c : s) t += c, t += '#';
int n = t.size(), center = 0, right = 0;
vector<int> p(n);
for (int i = 0; i < n; ++i) {
int mir = 2 * center - i;
if (i < right) p[i] = min(right - i, p[mir]);
while (i - p[i] - 1 >= 0 && i + p[i] + 1 < n && t[i-p[i]-1] == t[i+p[i]+1]) ++p[i];
if (i + p[i] > right) center = i, right = i + p[i];
}
return p;
}
  • 插入 # 后统一奇偶。
  • 原串回文长度与 p 数组需要换算。

最小表示法#

求循环同构字符串的字典序最小旋转。

  • 双指针 i、j 比较两个候选起点。
  • 失配后跳过不可能成为最优的区间。
  • 复杂度 O(n)O(n)

后缀自动机 SAM#

SAM 表示一个字符串所有子串的自动机。

  • 不同子串数量:(len[v]len[link[v]])\sum (len[v]-len[link[v]])
  • 可求每个子串出现次数。
  • 适合在线扩展。

回文自动机 PAM#

维护所有不同回文子串。

  • 两个根:长度 -1 和 0。
  • 每加入一个字符,最多新增一个回文节点。
  • 适合回文计数和回文 DP。

字符串题选型#

先判断是单模式、多模式、回文、子串排序还是动态维护。

  • 单模式:KMP/Z。
  • 多模式:AC 自动机。
  • 回文:Manacher/PAM。
  • 子串排名:SA/SAM。
  • 动态字典:Trie。

高频模板训练卡#

这一组训练卡用于把“09_字符串算法”转化为赛场识别能力。每张卡都包含题目信号、模板选择、复杂度、反例和实现检查。

卡 1:KMP#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 KMP。
  • 优先模板:使用 KMP 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 KMP 解决一道模板题并解释每个数组含义。

卡 2:Z 函数#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 Z 函数。
  • 优先模板:使用 Z 函数 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 Z 函数 解决一道模板题并解释每个数组含义。

卡 3:Trie#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 Trie。
  • 优先模板:使用 Trie 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 Trie 解决一道模板题并解释每个数组含义。

卡 4:01 Trie#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 01 Trie。
  • 优先模板:使用 01 Trie 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 01 Trie 解决一道模板题并解释每个数组含义。

卡 5:字符串哈希#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 字符串哈希。
  • 优先模板:使用 字符串哈希 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 字符串哈希 解决一道模板题并解释每个数组含义。

卡 6:双哈希#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 双哈希。
  • 优先模板:使用 双哈希 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 双哈希 解决一道模板题并解释每个数组含义。

卡 7:Manacher#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 Manacher。
  • 优先模板:使用 Manacher 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 Manacher 解决一道模板题并解释每个数组含义。

卡 8:AC 自动机#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 AC 自动机。
  • 优先模板:使用 AC 自动机 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 AC 自动机 解决一道模板题并解释每个数组含义。

卡 9:后缀数组#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 后缀数组。
  • 优先模板:使用 后缀数组 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 后缀数组 解决一道模板题并解释每个数组含义。

卡 10:后缀自动机#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 后缀自动机。
  • 优先模板:使用 后缀自动机 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 后缀自动机 解决一道模板题并解释每个数组含义。

卡 11:回文自动机#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 回文自动机。
  • 优先模板:使用 回文自动机 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 回文自动机 解决一道模板题并解释每个数组含义。

卡 12:最小表示法#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 最小表示法。
  • 优先模板:使用 最小表示法 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 最小表示法 解决一道模板题并解释每个数组含义。

卡 13:字典序比较#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 字典序比较。
  • 优先模板:使用 字典序比较 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 字典序比较 解决一道模板题并解释每个数组含义。

卡 14:LCP 查询#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 LCP 查询。
  • 优先模板:使用 LCP 查询 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 LCP 查询 解决一道模板题并解释每个数组含义。

卡 15:多模式匹配#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 多模式匹配。
  • 优先模板:使用 多模式匹配 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 多模式匹配 解决一道模板题并解释每个数组含义。

卡 16:禁串 DP#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 禁串 DP。
  • 优先模板:使用 禁串 DP 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 禁串 DP 解决一道模板题并解释每个数组含义。

卡 17:循环同构#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 循环同构。
  • 优先模板:使用 循环同构 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 循环同构 解决一道模板题并解释每个数组含义。

卡 18:最长重复子串#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 最长重复子串。
  • 优先模板:使用 最长重复子串 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 最长重复子串 解决一道模板题并解释每个数组含义。

卡 19:不同子串计数#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 不同子串计数。
  • 优先模板:使用 不同子串计数 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 不同子串计数 解决一道模板题并解释每个数组含义。

卡 20:前缀周期#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 前缀周期。
  • 优先模板:使用 前缀周期 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 前缀周期 解决一道模板题并解释每个数组含义。

卡 21:border 树#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 border 树。
  • 优先模板:使用 border 树 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 border 树 解决一道模板题并解释每个数组含义。

卡 22:字符串 DP#

  • 题目信号:题目涉及匹配、前缀、回文、子串、字典序或 字符串 DP。
  • 优先模板:使用 字符串 DP 模板。
  • 核心不变量:已匹配信息或自动机状态能被复用,不重复扫描。
  • 复杂度目标:多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。
  • 不适用场景:字符集巨大、动态修改或哈希碰撞要求严格证明时要换模型。
  • 实现检查:检查下标换算、分隔符、fail 指针、取模负数。
  • 边界样例:空串、单字符、全相同字符、模式串等于文本。
  • 训练题型:用 字符串 DP 解决一道模板题并解释每个数组含义。

本章赛前默写任务#

  • 默写 KMP 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 Z 函数 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 Trie 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 01 Trie 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 字符串哈希 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 双哈希 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 Manacher 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 AC 自动机 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 后缀数组 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 默写 后缀自动机 的模板,并写出 多数基础字符串模板 O(n),AC 自动机 O(总长度 + 文本长度)。。
  • 为本章任选 3 个模板各写一个最小输入。
  • 为本章任选 3 个模板各写一个会使错误实现失败的反例。
  • 把本章所有模板整理到个人代码库,并标注 0-index / 1-index。

字符串算法赛场自检表#

  • 单模式匹配优先想到 KMP 或 Z 函数。
  • 多模式匹配优先想到 Trie + AC 自动机。
  • 回文半径优先想到 Manacher。
  • 子串快速比较优先想到 Hash,严格场景考虑后缀数组。
  • 字符集大小是否影响 Trie 数组开法?
  • 分隔符是否保证不出现在原字符串中?
  • 哈希取模后是否处理负数?
  • fail 指针是否 BFS 构建?
  • 插入特殊字符后,答案下标是否正确换回原串?
  • 全相同字符和单字符样例是否通过?

09_字符串算法:详细训练清单#

本清单用于把章节知识拆成可执行的小任务,偏 OI/ACM 赛场使用。

训练点 1:KMP#

  • 识别信号:题面出现与“KMP”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“KMP”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 2:Z 函数#

  • 识别信号:题面出现与“Z 函数”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“Z 函数”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 3:Trie#

  • 识别信号:题面出现与“Trie”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“Trie”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 4:01 Trie#

  • 识别信号:题面出现与“01 Trie”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“01 Trie”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 5:字符串哈希#

  • 识别信号:题面出现与“字符串哈希”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“字符串哈希”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 6:双哈希#

  • 识别信号:题面出现与“双哈希”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“双哈希”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 7:Manacher#

  • 识别信号:题面出现与“Manacher”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“Manacher”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 8:AC 自动机#

  • 识别信号:题面出现与“AC 自动机”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“AC 自动机”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 9:后缀数组#

  • 识别信号:题面出现与“后缀数组”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“后缀数组”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 10:后缀自动机#

  • 识别信号:题面出现与“后缀自动机”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“后缀自动机”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 11:回文自动机#

  • 识别信号:题面出现与“回文自动机”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“回文自动机”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 12:最小表示法#

  • 识别信号:题面出现与“最小表示法”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“最小表示法”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 13:LCP#

  • 识别信号:题面出现与“LCP”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“LCP”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 14:border#

  • 识别信号:题面出现与“border”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“border”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 15:周期#

  • 识别信号:题面出现与“周期”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“周期”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 16:禁串 DP#

  • 识别信号:题面出现与“禁串 DP”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“禁串 DP”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 17:KMP#

  • 识别信号:题面出现与“KMP”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“KMP”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 18:Z 函数#

  • 识别信号:题面出现与“Z 函数”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“Z 函数”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 19:Trie#

  • 识别信号:题面出现与“Trie”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“Trie”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 20:01 Trie#

  • 识别信号:题面出现与“01 Trie”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“01 Trie”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 21:字符串哈希#

  • 识别信号:题面出现与“字符串哈希”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“字符串哈希”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 22:双哈希#

  • 识别信号:题面出现与“双哈希”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“双哈希”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 23:Manacher#

  • 识别信号:题面出现与“Manacher”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“Manacher”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。

训练点 24:AC 自动机#

  • 识别信号:题面出现与“AC 自动机”相关的限制、操作或查询时,先判断能否套用本章模型。
  • 建模步骤:写出输入对象、维护状态、允许操作、目标答案,再决定使用暴力、模板或优化。
  • 模板要求:能默写核心代码,并说明变量含义、初始化方式和循环边界。
  • 复杂度要求:写出预处理、单次操作、总复杂度,并确认能通过最大数据范围。
  • 反例检查:构造最小规模、全相等、极端值、重复值、无解或刚好可行的样例。
  • 复盘要求:若做错,记录错因是建模、证明、复杂度、边界、溢出还是模板不熟。
  • 扩展任务:把“AC 自动机”与至少一个其他专题组合,例如二分、图论、DP、数据结构或数学。
分享

如果這篇文章對你有幫助,歡迎分享給更多人!

字符串算法
https://lemusakuya.com/posts/study-notes/algorithm/09_字符串算法/
作者
レム・咲く夜
發布於
2026-06-03
許可協議
CC BY-NC-SA 4.0

部分資訊可能已經過時

目錄