Trie & AC 自动机
本篇为学习笔记。
Trie 字典树
先放张来自 OI Wiki 的图——

可以看到每个节点都有一个编号,每个编号都代表了一个字符串。
节点之间的有向边边上有字符 \((u,v)=c\),即 \(u\) 所代表的字符串在结尾添加 \(c\) 后为 \(v\) 代表的字符串。
一般根节点编号为 \(0\)。
对于每个节点,需要存当前节点代表的字符串是否存在(存在的个数)。
AC 自动机
前置知识:自动机。
AC 自动机常用于解决多模式串匹配的任务。
众所周知 KMP 虽然是线性的,但是一次只能匹配一个模式串。而 AC 自动机一次可以匹配多个模式串。
考虑:
- 对模式串建立 Trie。
- 从根节点出发,每新增一个字符,就走相应的边。
- 如果不存在相应边,回到根节点。
- 如果走到的节点存在,则匹配成功。
但是这样会少匹配。比如如果有模式串 \(\texttt{abe},\texttt{bc}\),文本串 \(\texttt{abcde}\),那么会在 \(\texttt{ab\color{red}{e}}\) 处失配,回到根节点,错失了 \(\texttt{bc}\)。
AC 自动机利用一个 fail 指针来辅助多模式串的匹配。
什么是 fail 指针?
它是每个节点都有的指针,指向当前(节点所代表的)字符串的(Trie 上已存在的)最长真后缀。
举个例子,上图中 \(12\) 代表 \(\texttt{caa}\),它指向的是 \(5:\texttt{aa}\)。又如 \(10\to 4,13\to 6,14\to 7\cdots\)。
那么 fail 指针有什么用?
依然以模式串 \(\texttt{abe},\texttt{bc}\),文本串 \(\texttt{abcde}\) 为例,那么在 \(\texttt{ab\color{red}{e}}\) 处失配后,会跳到代表 \(\texttt{b}\) 的节点,尝试继续匹配。
那么 fail 指针怎么建?
考虑到 fail 指针指向的是最长真后缀,故指向的节点深度一定更高。bfs 解决:
- 树根先入队
- 队列非空时,取出队首节点 \(u\),遍历每个字母 \(c\),记 \(u[c]\) 为对应的儿子
- 若 \(u[c]\) 存在,将 \(u[c].\text{fail}\gets u.\text{fail}[c]\)
- 反之,\(u[c]\gets u.\text{fail}[c]\)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具