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年产生于贝尔实验室,是著名的多模匹配 ...
随机推荐
- CentOS 7下sqlite3的问题修复
Centos7下的nltk启动问题 CentOS 7, Python 3.6,ipython 6.0.0 问题描述 ipython 启动ipython命令 import nltk 爆出以下的错误信息: ...
- 【转】程序员应该了解的——除了coding我们还有很多事要做
from : http://www.cnblogs.com/lingyun1120/archive/2011/10/09/2203306.html try { if (you.believe(it) ...
- 【ACM非算法部分】STL汇总
stackqueuepriority_queuemapsetpair ====================================== stack:(栈) 包含:#include<s ...
- 21天学通C++_Day1
被阿里实习生的第一轮电话面试刷掉以后,幡然醒悟,发现以前学习的C++基础一点都不扎实.为了把基础打扎实,重新学习一遍:为了让自己不放弃,也顺便可以把当天学到的东西记录下来,开始了写博客. 学习书籍:& ...
- kali视频(1-5)
第二周 kali视频(1-5) 1.kali安装 2.基本配置 vmtools安装过程. 3.安全渗透测试一般流程 4.信息搜集之GoogleHack 5.信息搜集之目标获取 1.kali安装 直接在 ...
- SOA的挑战:实体集合【转】
SOA的挑战:实体集合 发布日期 : 2005-11-06 | 更新日期 : 2005-11-06 Ramkumar Kothandaraman 微软公司 适用于: Microsoft® Visua ...
- 好用的python第三方库
参考连接:http://python.jobbole.com/84464/ https://www.zhihu.com/question/20501628 python每日技术更新:https://g ...
- 也谈TDD,以及三层架构、设计模式、ORM……没有免费的午餐,选择了,必付出代价
想在园子里写点东西已经很久了,但一直没有落笔,忙着做 一起帮 的开发直播,还有些软文做推广,还要做奶爸带孩子,还要……好吧,我承认,真正的原因是: 太特么的难写了! 但再难写也要写啊,要等到“能写好了 ...
- CLR值类型和引用类型
知识点:引用类型.值类型.装箱.拆箱 CLR支持两种类型:引用类型和值类型.引用类型在堆上分配内存,值类型在线程栈上分配内存.值类型与引用类型如下所示: 值类型对象有两种表示形式:未装箱和已装箱.将一 ...
- ubantu 安装tree命令
前提:必须安装好VMware tools 在linux系统中找不到tree这个命令时,需要安装,如ubuntu用下面的命令就可以安装tree这个命令工具,其他linux系统类似. 1 sudo apt ...