今天花了半天肝下AC自动机,总算啃下一块硬骨头,熬夜把博客赶出来。。

正如许多博客所说,AC自动机看似很难很妙,而事实上不难,但的确很妙。笼统地说,AC自动机=Trie+KMP,但是仅仅知道这个并没有什么用,该写不出来的还是写不出来,必须理解每一步的精确含义。KMP算法的精髓是“用自己匹配自己”,即:如果前i个字符失配时应该转移到第j个字符,那么前i+1个字符失配时应该比较i+1与j+1处的字符。AC自动机是一样的道理,只不过将图画在一颗Trie上,看起来不像KMP那样直观。用语言去描述构造失配边时的过程是这样的:设当前结点和字符分别为u和c,父亲结点的失配边指向v,如果v下有对应c的边,那么说明u的失配边应该指向ch[v][c](因为恰好匹配,公共前缀不变);否则将u视为v的子结点(也可以理解为给v建一个虚拟子结点对应c,然后递归求解虚拟结点的失配边),去找v的失配边指向的结点,直到找到或者v为根结点。

下面用一个例子解释一下这个过程:

现在为Trie加入失配边(这张图有点乱,建议一个点一个点地捋,找到规律就好办了)

朴素的AC自动机就长这样了(红色的边代表失配边)。每次匹配字符串时,如果失配,就沿着失配边一直走直到匹配;如果匹配就对当前结点追溯其失配边,找到所有在自动机中的当前匹配到的字符串的后缀(因为它们本不会被计入答案)。

对于上面的例子,匹配时访问的结点顺序为:1,7,8,23,24,18,19,15,22,3。由于与KMP算法一样,至多回溯O(m)次,因此保证了复杂度是线性的O(n+m)。

事实上,AC自动机有一些优化的方法:  

1.既然每次匹配时我要沿失配边找sum不为0的结点(即存在自动机中的完整字符串,而不是字符串的前缀),那么我为什么不直接开一个数组去存这些失配边指向的第一个sum不为0的结点呢?这样明显剩下一些时间。尽管理论上成立,但是我不建议使用这个优化,因为它不仅使AC自动机的代码变得冗长,还不一定有成效(毕竟只是常数优化)。

2.按我上面的介绍,失配与匹配是两种不同的状态,有不同的应对方法,但实际上两者差距并不大,仔细想想我上文的解释:将u视为v的子结点,进行递归求解,也就是说,失配其实就是匹配到了失配边所连接的结点的子结点。两者密不可分,甚至可以通过一些技巧将两者用同样的方法进行处理——只要将建立失配边的过程中,u的c子结点不存在时,ch[u][c]赋值为ch[fail[u]][c]即可。然后匹配时就不需要考虑失配的情况了,统一按匹配的情况进行转移,写起来方便多了。

例题:HDU 2222 Keywords Search

这道题就是一道AC自动机模板题,除了注意初始化外没有坑,适合上手。

其他题目以后更新。(其实是因为我才学,也只做了一道题)

代码

UPD(2017.12.24):

例题二:UVaLive 4670 Dominating Patterns(鉴于UVaLive的网站很多人上不去,包括我,我就传vjudge的链接了)P.S.这道题在洛谷上有原题,数据可能加强了一点,这里放出传送门

这题也算是模板题,注意一下模板串可以重复,推荐用map存重复的字符串的编号。还有就是数据范围,哪个是n,哪个是模板串长度要分清(我一开始就在这里RE一次)。

代码

AC自动机讲解的更多相关文章

  1. AC自动机讲解+[HDU2222]:Keywords Search(AC自动机)

    首先,有这样一道题: 给你一个单词W和一个文章T,问W在T中出现了几次(原题见POJ3461). OK,so easy~ HASH or KMP 轻松解决. 那么还有一道例题: 给定n个长度不超过50 ...

  2. AC自动机讲解超详细

    begin:2019/5/2 感谢大家支持! AC自动机详细讲解 AC自动机真是个好东西!之前学KMP被Next指针搞晕了,所以咕了许久都不敢开AC自动机,近期学完之后,发现AC自动机并不是很难,特别 ...

  3. [BZOJ4327]:[JZOI2012]玄武密码(AC自动机)

    题目传送门 题目描述: 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此.  ...

  4. [BZOJ3940]:[Usaco2015 Feb]Censoring(AC自动机)

    题目传送门 题目描述: FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过105的字符串S.他有一个包含n个单词的列表,列表里的n个单词记为t1…tN.他希望从S中删除这些单词.FJ每次在S中 ...

  5. [BZOJ1030]:[JSOI2007]文本生成器(AC自动机+DP)

    题目传送门 题目描述 JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群, 他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是 ...

  6. [BZOJ1195]:[HNOI2006]最短母串(AC自动机+BFS)

    题目传送门 题目描述 给定n个字符串(S1,S2,…,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,…,Sn)都是T的子串. 输入格式 第一行是一个正整数n,表示给定的字符串的个数 ...

  7. 算法总结篇---AC自动机

    目录 写在前面 算法流程 引例: 概述: Trie树的构建(第一步) 失配指针(第二步) 构建失配指针 字典树和字典图 多模式匹配 例题 写在前面 鸣谢: OiWiki 「笔记」AC 自动机---Lu ...

  8. AC自动机基础知识讲解

    AC自动机 转载自:小白 还可参考:飘过的小牛 1.KMP算法: a. 传统字符串的匹配和KMP: 对于字符串S = ”abcabcabdabba”,T = ”abcabd”,如果用T去匹配S下划线部 ...

  9. 一个在开源中国博客上讲解的AC自动机

    原文出处:http://my.oschina.net/amince/blog/196426 原 荐 AC(Aho—Corasiek) 多模式匹配算法 摘要 如何在一篇文章中,搜索多个关键字,如何快速查 ...

随机推荐

  1. Linux chown

    在学习 兄弟连 linux教学视频 的时候,我将所学的 linux 命令记录在我的博客中,方便自己查阅. 权限管理命令: chown 基础的命令 命令名称:chown 命令英文原意:change fi ...

  2. 微信小程序基于最新版1.0开发者工具分享-小试牛刀(视频)+发布流程

    第一章:小程序初级入门教程 小试牛刀[含视频] 视频地址:https://v.qq.com/x/page/i0554akzobq.html 这一章节中,我们尝试着写一个最简单的例子,包含 2 个静态页 ...

  3. dataGrideView的使用

    总的连接地址:http://group.cnblogs.com/topic/40730.html 微软解说:https://msdn.microsoft.com/zh-cn/library/syste ...

  4. xamarin android布局

    xamarin android布局练习(1) xamarin android布局练习,基础非常重要,首先要学习的就是android的布局练习,xamarin也一样,做了几个xamarin androi ...

  5. SQL语句 我喜欢上海

    select * from [user] wherer name like '上海%'

  6. springBoot系列教程08:拦截器(Interceptor)的使用

    拦截器intercprot  和 过滤器 Filter 其实作用类似 在最开始接触java 使用struts2的时候,里面都是filter 后来springmvc时就用interceptor 没太在意 ...

  7. 自己做一台3D打印机到底有多难?(附教程)

    •    微博: 小样儿老师2015 初识 3D打印技术,即快速成形技术,它是一种以数字模型文件为基础,运用粉末状金属或塑料等可粘合材料,通过逐层打印的方式来构造物体的技术,3D打印机则出现在上世纪9 ...

  8. Layout 不可思议(一)—— CSS 实现自适应的正方形卡片

    最近被一个布局问题给难住了,枉我一向自称掌握最好的前端技能是 CSS,写完博客就得敷脸去 需求是实现一个自适应的正方形卡片,效果如下: 顺便(开个坑)写个系列,总结那些设计精妙的布局结构 本次页面的 ...

  9. 用 CSS3 做一个流星雨动画

    昨天 UI 提交过来一个登录页的设计稿,要求背景有一个流星雨动画,做完之后觉得挺有趣,分享一下~ 一.流星动画 首先创建一个 div 作为画布 <div id="stars" ...

  10. Linux程序包管理rpm与yum

    Linux程序包管理 Linux中软件的安装主要有两种形式:一种是直接下载源代码包自行编译后安装,另一种直接获取rpm软件包进行安装. 程序的组成部分: 二进制程序:程序的主体文件,比如我们运行一个l ...