AC自动机详解
概述
AC自动机全称Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法。
考虑这样一个场景,给出L个模式字符串(加总长度为N),以及长度为M大文本,要求从大文本中提取每个模式字符串出现的位置。如果使用KMP算法,时间复杂度将达到O(LM+N),而使用AC自动机可以在O(N+M)时间复杂度内解决这一问题,当L很大时,AC自动机的优势非常明显。
建立AC自动机
AC自动机实际上是前缀树,但是会引入一个与KMP类似的失败转移的概念。我们先为所有模式建立对应的前缀树,之后为每个前缀树结点添加一个指针fail,指向另外一个前缀树中的结点。每个前缀树中的结点实际上都代表了某个模式的一段前缀,我们之后将结点与其对应的前缀等同起来。令结点x的fail指针指向y(y不为x),其中y是x的后缀,且y是所有符合这类条件的结点中深度最大的(前缀长度最大的),我们称y是x的后缀结点,称x是y的伪父,显然伪父的伪父依旧还是伪父。可以很容易证明以x为起点沿着fail指针不断移动,可以遍历所有x的有效后缀,且访问到的结点深度递减。如果无法为结点的fail指针无法找到有效的结点,那么将fail指针指向前缀树的根结点root。
AC自动机的难度在于要如何为每个结点建立fail指针。由于fail指针指向的结点深度必然小于fail指针的持有者,因此可以用DP的思路,我们先为深度较小的结点建立fail指针,再为深度较大的结点建立fail指针。这个过程可以通过广度优先搜索算法实现。要建立x的fail指针,考虑到x.fail.father必然是x.father的某个有效后缀,因此我们可以通过以x.father为起点,沿着fail指针移动以寻找x.fail.father,并从而找到x.fail。这个过程十分类似于KMP中建立跳转表的过程,这里对其具体操作不再赘述。
使用AC自动机
如何使用AC自动机呢?我们维护一个轨迹结点trace,对于每个输入字符c,我们判断trace是否有c号孩子,如果有就将trace设置为其c号孩子,否则我们将trace设置trace.fail,并继续询问,直到trace成为root或者找到了c号孩子。重复上面过程直到读完文本。
若最后trace成功设置为其c号孩子,则我们称访问了c号孩子。可以证明若输入文本T中T[a...b]与某个模式p相匹配,那么当我们读入T[b]时,p和p的所有伪父中有且只有一个结点被访问。*对于任意c<a,a=<d<b,若trace匹配T[c...d],那么当我们读入T[d+1]时,若成功,trace将步进,若失败,则依旧能保证trace转移后c<=a,因为此时p的某个祖先结点已经做好了接盘的准备,故c始终会小于等于a,当c=a时,此时trace为p的祖先,因此直到读入T[b]时,trace必定匹配T[c...b],此时c<=a,因此trace是p或p的伪父。*通过这段证明我们基本可以了解到如何在AC自动机读取完文本后获取我们想要的结果,如果需要每个模式出现次数,可以得知每个模式的出现次数为其被访问次数加上其所有伪父被访问次数,而如果需要每个模式的匹配位置,思路也是类似,为每个模式维护被访问时读取字符的下标就可以了,整合上所有伪父的匹配位置即可得出。
时间复杂度
时间复杂度分为建立AC自动机的时间复杂度和匹配的时间复杂度。
设所有模式的长度和为n,文本长度为m。建立前缀树的时间复杂度为O(n),而建立fail指针的时间复杂度分析类似于KMP算法中建立跳转表的时间复杂度。我们可以定义每个结点x的fail指针指向的y结点的深度为x的“子深”,记作x.cd。很容易发现x.cd<=x.father.cd+1,而我们每次从x.father出发沿着fail指针移动,x的子深也在不断递减但不会低于0,在为某个模式上的结点建立fail时,每次后移最多提供1个子深,因此在创建模式pi时我们最多沿着fail指针移动了|pi|次,故创建所有模式总共沿着fail指针最多移动O(n)次,到此说明了建立fail指针的时间复杂度为O(n)。
对模式匹配,每当我们读入一个字符c时,trace或者向下移动(即有c号孩子)并结束或者沿着fail移动到某个自己的后缀上去。显然向下移动最多发生O(m)次,而沿着fail移动,就如同我所说的每次都必定会降低子深,而每次向下移动可以提供最多1子深,因此可以保证沿着fail移动的次数最多为O(m)次。故总的时间复杂度为O(m)。
时间复杂度的总和为O(n+m),空间复杂度为O(Cn),其中C为使用的字符集的大小(用于建立前缀树)。
AC自动机详解的更多相关文章
- [转] AC自动机详解
转载自:http://hi.baidu.com/nialv7/item/ce1ce015d44a6ba7feded52d AC自动机详解 AC自动机是用来处理多串匹配问题的,即给你很多串,再给你一篇文 ...
- Aho-Corasick 多模式匹配算法、AC自动机详解
Aho-Corasick算法是多模式匹配中的经典算法,目前在实际应用中较多. Aho-Corasick算法对应的数据结构是Aho-Corasick自动机,简称AC自动机. 搞编程的一般都应该知道自动机 ...
- AC自动机详解(附加可持久化AC自动机)
AC自动机 AC自动机,说白了就是在trie树上跑kmp(其实个人感觉比kmp容易理解).是一种多匹配串,单个主串的匹配.概括来说,就是将多个匹配串构造一个trie树,对于每个trie树的节点构造nx ...
- AC自动机详解 (P3808 模板)
AC自动机笔记 0.0 前言 哇,好久之前就看了 KMP 和 Trie 树,但是似乎一直没看懂 AC自动机?? 今天灵光一闪,加上之前看到一些博客和视频,瞬间秒懂啊... 其实这个玩意还是蛮好理解的. ...
- 【转】AC算法详解
原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和 ...
- hdu-Danganronpa(AC自动机)
Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft, t ...
- 算法模板——AC自动机
实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有 ...
- 病毒侵袭---hdu2896(AC自动机)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 输入的字符是所有可见的ASCII码(共有127个)所以要注意一下: 把结果存到一个数组中,然后输 ...
- 学习笔记:AC自动机
话说AC自动机有什么用......我想要自动AC机 AC自动机简介: 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配 ...
随机推荐
- TCP服务器端口数,最大连接数以及MaxUserPort的关系辨真
原文连接:http://www.jianshu.com/p/4a58761d758f 关于TCP服务器最大并发连接数有一种误解就是"因为端口号上限为65535,所以TCP服务器理论上的可承载 ...
- 数据展示Matplotlib
主要内容是Matplotlib库的基本使用和方法 1 Matplotlib库 1.1 Matplotlib的介绍 Python优秀的数据可视化第三方库 数据可视化就是将数据以特定的图形图像的方式展示出 ...
- laravel 中将DB::select 得到的内容转为数组
$sql = "select count(*) as num from api_log where uid='{$this->uid}'"; $ ...
- 深入了解zookeeper(三)
一.ZooKeeper 的实现 1.1 ZooKeeper处理单点故障 我们知道可以通过ZooKeeper对分布式系统进行Master选举,来解决分布式系统的单点故障,如图所示. 那么我们继续分析一下 ...
- 如何将u盘、移动硬盘转化为活动分区--绝招
https://jingyan.baidu.com/article/e75057f2a6a18aebc91a893e.html
- Consul做服务发现
使用Consul做服务发现的若干姿势 https://www.cnblogs.com/bossma/p/9756809.html 从2016年起就开始接触Consul,使用的主要目的就是做服务发现,后 ...
- 复制的web工程为什么不能部署到tomcat
An existing resource has been found at location D:\apache-tomcat-6.0.18\apache-tomcat-6.0.18\webapps ...
- slabtop 监控实时内核片缓存信息
使用 slabtop命令监控实时内核片缓存信息 默认情况下,sl ...
- mysql权限验证流程
mysql用户管理,逐级下查 mysql库的user表连接信息,全局权限db表记录用户对库的权限,对某个数据库的所有表的权限tables_priv 设置用户对表的权限columns_priv设置用户对 ...
- 安装appium需要注意的事项
参考 虫师 的博客园 :http://www.cnblogs.com/fnng/p/4560298.html 1.其中第二篇中,打开命令行用的不是windows中的cmd打开的界面,而是用node. ...