自动机相关
1|0前言
以下内容大多摘抄自 OI-Wiki 以及
2|0确定有限状态自动机(DFA)
2|1形式化定义
一个 确定有限状态自动机(DFA) 由以下五部分组成:
-
1.字符集(
) , 该自动机只能输入这些字符 -
2.状态集合(
) , 如果把一个 看成一张有向图,那么 中的状态就相当于图上的顶点。 -
3.起始状态(
) , ,是一个特殊的状态。起始状态一般用 表示,为了避免混淆,本文中使用 。 -
4.接受状态集合(
) , , 是一组特殊的状态。 -
5.转移函数(
) , 是一个接受两个参数返回一个值的函数,其中第一个参数和返回值都是一个状态,第二个参数是字符集中的一个字符。如果把一个 看成一张有向图,那么 中的转移函数就相当于顶点间的边,而每条边上都有一个字符。
当一个
如果一个状态
我们扩展定义转移函数
如,一个接受且仅接受字符串 "a", "ab", "aac" 的
3|0常见自动机
3|1字典树
字典树接受且仅接受指定的字符串集合中的元素,说白了就是你输入啥它就怎么建树。
转移函数就是
3|2ACAM AC自动机
AC 自动机也是一类常用的DFA,有完整的 DFA 五要素,分别是起点
解决问题
AC 自动机用于解决 多模式串 匹配问题:给定多个模式串
算法详解
如果直接用 KMP 进行暴力,复杂度是
步骤1:建 trie 树
这部分的操作就是用模式串建立字典树来进行操作。
步骤2:Fail指针的建立
类似于 KMP 中的
用白话说,Fail 指针的定义是:如果一个点
图中
-
首先我们要知道两个点
一、
可能有两种含义:1.存节点
的树边的终点。如图中 ;2.存节点
的转移边的终点,如 ,因为这种边在图中太多了,就没有表示出来。二、这棵 Trie 树包含三种边,回跳边 、转移边 和 树边。
(1)树边:树边就是我们在第一步建立 Trie 树形成的边;
(2)回跳边:回跳边指向父节点的回跳边所指节点的儿子,四个点(
)构成一个四边形。实际上我们就是通过这个思想来构建 Fail 指针的。回跳边的方向就是 Fail 指针的方向,并且这种边并不实际存在。所以我们可以发现 就是存的节点 的回跳边的终点;(3)转移边:转移边指向当前节点的回跳边所指节点的儿子,三个点(
)构成一个三角形。我们通过建立这种边来完成最后文本串的遍历。
那么什么时候建回跳边,什么时候建转移边呢?我们看图说话。
如图:
当
如图:
当
怎么理解呢,还是看图:
我们想给最下面的
,我们就能得到
我们最终便能得出
如果你还是不能理解,一个个对应一下,仔细一点就好了。
通过上述的过程我们可以看出,回跳边和转移边的建立是有赖于深度较小的点的。因此,我们在建立 Trie 树的时候,是采取的 BFS 的方法来进行操作的。
至此,我们总结一下
-
把深度为
的真实节点入队,因为它们的 Fail 指针肯定指向 root -
节点
出队,枚举 的 个儿子1.若儿子真实存在,建回跳边,把儿子入队
2.若非真实存在,节点
自建转移边。
Code:
步骤3:查询单词出现个数
扫描文本串,依次取出字符
-
指针走主串对应的节点,沿着 树边 或者是 转移边 走,保证不回退。 -
指针沿着回跳边搜索模式串,每次从当前节点走到根节点,把当前节点中的所有后缀模式串 一网打尽,保证不漏解。 -
扫描完主串,返回答案。
(董晓大爹的评论:"算法一边走文本串,一边把当前穿的所有后缀串搜出来,实在是强。")
Code:
应用
AC自动机能够与动态规划或者矩阵快速幂等相结合,有着很好的性质。这里就不再一一赘述(因为我也不会/kk)
3|3SAM后缀自动机
不会,咕咕
3|4PAM回文自动机
不会,咕咕
__EOF__

本文链接:https://www.cnblogs.com/bloodstalk/p/17432889.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义