[转] AC自动机详解
转载自:http://hi.baidu.com/nialv7/item/ce1ce015d44a6ba7feded52d
AC自动机详解
AC自动机是用来处理多串匹配问题的,即给你很多串,再给你一篇文章,让你在文章中找这些串是否出现过,在哪出现。也许你考虑过AC自动机名字的含义,我也有过同样的想法。你现在已经知道KMP了,他之所以叫做KMP,是因为这个算法是由Knuth、Morris、Pratt三个提出来的,取了这三个人的名字的头一个字母。那么AC自动机也是同样的,他是Aho-Corasick。所以不要再YY地认为AC自动机是AC(cept)自动机,虽然他确实能帮你AC一点题目。
。。。扯远了。。。
要学会AC自动机,我们必须知道什么是Trie,即字母树。如果你会了,请跳过这一段
Trie是由字母组成的。
先看张图:
这就是一棵Trie树。用绿色标出的点表示一个单词的末尾(为什么这样表示?看下去就知道了)。树上一条从root到绿色节点的路径上的字母,组成了一个“单词”。
/* 也许你看了这一段,就知道如何构建Trie了,那请跳过以下几段。*/
那么如何来构建一棵Trie呢?就让我从一棵空树开始,一步步来构建他。
一开始,我们有一个root:
现在,插入第一个单词,she。这就相当于在树中插入一条链。过程很简单。插完以后,我们在最后一个字母’e’上加一个绿色标记,结果如图:
再来一个单词,shr(什么词?…..右位移啊)。由于root下已经有’s’了,我们就不重复插入了,同理,由于’s’下有’h’了,我们也略过他,直接在’h’下插入’r’,并把’r’标为绿色。结果如图:
按同样的方法,我们继续把余下的元素插进树中。
最后结果:
也就是这样:
好了,现在我们已经有一棵Trie了,但这还不够,我们还要在Trie上引入一个很强大的东西:失败指针或者说shift数组或者说Next函数 …..你爱怎么叫怎么叫吧,反正就是KMP的精华所在,这也是我为什么叫你看KMP的原因。
KMP中我们用两个指针i和j分别表示,A[i-j+ 1..i]与B[1..j]完全相等。也就是说,i是不断增加的,随着i的增加j相应地变化,且j满足以A[i]结尾的长度为j的字符串正好匹配B串的前 j个字符,当A[i+1]<>B[j+1],KMP的策略是调整j的位置(减小j值)使得A[i-j+1..i]与B[1..j]保持匹配且新的B[j+1]恰好与A[i+1]匹配(从而使得i和j能继续增加)。
Trie树上的失败指针与此类似。
假设有一个节点k,他的失败指针指向j。那么k,j满足这个性质:设root到j的距离为n,则从k之上的第n个节点到k所组成的长度为n的单词,与从root到j所组成的单词相同。
比如图中she中的’e’的失败指针就应该指向her中的’e’。因为:
图中红框部分是完全一样的。
那么我们要怎样构建这个东西呢?其实我们可以用一个简单的BFS搞定这一切。
对于每个节点,我们可以这样处理:设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,他的儿子中也有字母为C的节点。然后把当前节点的失败指针指向那个字目也为C的儿子。如果一直走到了root都没找到,那就把失败指针指向root
最开始,我们把root加入队列(root的失败指针显然指向自己),这以后我们每处理一个点,就把它的所有儿子加入队列,直到搞完。
至于为什么这样就搞的定,我们讲下去就知道了。
好了,现在我们有了一棵带失败指针的Trie了,而我的文章也破千字了,接下来,我们就要讲AC自动机是怎么工作的了。
AC自动机是个多串匹配,也就是说会有很多串让你查找,我们先把这些串弄成一棵Trie,再搞一下失败指针,然后我们就可以开始AC自动机了。
一开始,Trie中有一个指针t1指向root,待匹配串(也就是“文章”)中有一个指针t2指向串头。
接下来的操作和KMP很相似:如果t2指向的字母,是Trie树中,t1指向的节点的儿子,那么t2+1,t1改为那个儿子的编号,否则t1顺这当前节点的失败指针向上找,直到t2是t1的一个儿子,或者t1指向根。如果t1路过了一个绿色的点,那么以这个点结尾的单词就算出现过了。或者如果t1所在的点可以顺着失败指针走到一个绿色点,那么以那个绿点结尾的单词就算出现过了。
我们现在回过来讲讲失败指针。实际上找失败指针的过程,是一个自我匹配的过程。
如图,现在假定我们确定了深度小于2(root深度为1)的所有点的失败指针,现在要确定e。这就相当于我们有了这样一颗Trie:
而文章为’she’,要查找’e’在哪里出现。我们接着匹配’say’,那’y’的失败指针就确定了。
好好想想。前面讲的BFS其实就是自我匹配的过程,这也是和KMP很相似的。
好了,就写到这吧,有不明白可以留言或发邮件给我(drdarkraven@gmail.com),或者在推上fo我(@sdraven)....
[转] AC自动机详解的更多相关文章
- Aho-Corasick 多模式匹配算法、AC自动机详解
Aho-Corasick算法是多模式匹配中的经典算法,目前在实际应用中较多. Aho-Corasick算法对应的数据结构是Aho-Corasick自动机,简称AC自动机. 搞编程的一般都应该知道自动机 ...
- AC自动机详解(附加可持久化AC自动机)
AC自动机 AC自动机,说白了就是在trie树上跑kmp(其实个人感觉比kmp容易理解).是一种多匹配串,单个主串的匹配.概括来说,就是将多个匹配串构造一个trie树,对于每个trie树的节点构造nx ...
- AC自动机详解
概述 AC自动机全称Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法. 考虑这样一个场景,给出L个模式字符串(加总长度为N),以及长度为M大文本, ...
- 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年产生于贝尔实验室,是著名的多模匹配 ...
随机推荐
- Eclipse恢复初始界面&打开视图
恢复初始界面: 单击菜单栏的windows主菜单,在子菜单里选择 Reset Perspective 会弹出各对话框 ,点 ok就可以了 打开视图:Windows->Show View 其中Ot ...
- 【转】如何编译安装PHP扩展
本文参考 一开始安装PHP的时候,我们并不知道需要哪些扩展,所以只有等到我们真正用到的时候才想办法去安装. 安装PHP扩展最简单的办法就是 sudo apt-get install php5-xxx ...
- 判断UserAgent是否来自微信
iso: Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko ...
- linux shell命令的常用快捷键
一些shell的常用快捷键. Ctrl + a 切换到命令行开始 Ctrl + e 切换到命令行末尾 Ctrl + l 清除屏幕内容 Ctrl + u 清除剪切光标之前的内容 Ctrl + ...
- php 时间函数参考
time()在PHP中是得到一个数字,这个数字表示从1970-01-01到现在共走了多少秒,很奇怪吧 不过这样方便计算, 要找出前一天的时间就是 time()-60*60*24; 要找出前一年的时间就 ...
- SQL注入原理二
随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多. 但是由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候 ,没有对用户输入数据的合法性进行判断,使应用程序存 ...
- Python 强大而易用的文件操作(转载)
在Python中可以很方便地做一些诸如浏览目录,创建文件夹,删除文件夹等等的操作. 对文件系统的访问大多通过os模块来实现,因为Python是多平台的,os模块只是前端,具体的实现还是由具体的系统来完 ...
- 不相交集合ADT
不相交集合数据结构保持一组不相交的动态集合S={S1,S2,...,SK},每个集合通过一个代表来识别,代表即集合中的某个成员. 如果x表示一个对象,不相交集合支持以下操作: MAKE-SET(x): ...
- JS的this本质
1.this究竟为何物? 1.1 全局上下文(Global context ) 在全局运行上下文中(在任何函数体外部),this 指代全局对象window,无论是否在严格模式下. alert(this ...
- linux exec函数家族
1.exec家族一共有六个函数,分别是: (1)int execl(const char *path, const char *arg, ......); (2)int execle(const ch ...