最近学习了AC自动机,做了notonlysuccess大牛里面的题,也该来个总结了。

AC自动机(Aho-Corasick Automaton)在1975年产生于贝尔实验室,是著名的多模匹配算法之一。

至于算法的讲解,notonlysuucess大牛极力推荐

http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf
http://www.docin.com/p-46845432.html(上边原文地址如果无法访问的话可以访问这一个~)

我也是看着这个学习的。讲得真的挺好的。唯一的缺点就是这个pdf是英文的。不过都是简单的英文,阅读起来没有太大障碍,而且内容短小精悍。我也大力推荐这篇pdf,对于其中的out函数一定要好好理解。。。

先贴一下模板(其实就是Notonlysuccess的模板了……)

struct AC_Automaton
{
int fail[NODE],son[NODE][4],idx,val[NODE];
void clear()
{
memset(son[0],0,sizeof son[0]);
idx = 1;
}
void insert(char *s)
{
int p = 0;
for (; *s; ++s) {
const int c = ID[(int)*s];
if (!son[p][c]) {
memset(son[idx],0,sizeof son[idx]);
val[son[p][c] = idx++] = 0;
}
p = son[p][c];//经常忘了写这句话。。
}
++val[p];
}
void construct()//这边用了notonlysuccess大牛的一点优化:
{
for (int i = 0; i < 4; ++i)
if (son[0][i]) {
q.push(son[0][i]);
fail[son[0][i]] = 0;
}
while (!q.empty()) {
const int u = q.front(); q.pop();//经常忘了出队。。
for (int i = 0; i < 4; ++i) {
int &v = son[u][i];
if (v) {
fail[v] = son[fail[u]][i];//由于son[fail[u]]之前已经赋过值了,就可以直接赋值。
q.push(v);
val[v] += val[fail[v]];//这边根据具体题目而定。
}else v = son[fail[u]][i];//这边把某个节点的儿子不一定是在trie上的真实儿子,还有可能是通过fail到达的。总之是下一个合法的儿子,这样可以省掉找fail。
}
}
}
void dfs(int s,const int dep)//具体题目需要
{
if (dep == 4) {
for (int i = 0; i < idx; ++i) {
if (f[i][s] == -1) continue;
for (int j = 0; j < 4; ++j)
if (num[j] < app[j])
if (f[son[i][j]][s + st[j]] < f[i][s] + val[son[i][j]])
f[son[i][j]][s + st[j]] = f[i][s] + val[son[i][j]];
}
return;
}
for (int i = 0; i <= app[dep]; ++i) {
num[dep] = i;
dfs(s,dep + 1);
s += st[dep];
} }
void init()//具体题目需要
{
for (int i = 0; i < idx; ++i)
for (int j = 0; j < tot; ++j) f[i][j] = -1;
f[0][0] = 0;
}
}AC;

  

AC自动机主要都是套上位上的DP。

每个trie上的节点都是一个状态。每一个串都只会在Trie上对应一个节点。

例题的话都是Notonlysuccess里面的了。

他都有题解和某些题目的简述。

这里提几道需要注意的题目吧。

hdu3065,这道题直接用AC做的话是可以构造数据卡T掉(如原串是AAAAAAAAAAAAAAA....,病毒是A,AA,AAA,AAAA....)这样复杂度就很高了。 改进方法是先标记最后再从trie倒着更新上去。

hdu3341,这题不用散列表,直接用状压就可以了,也就是第一位是num['A']+1进制,第二位是num['C']+1进制依此类推,记得数据范围要开到11^4

hdu3247,直接从每个源文件的节点转移就可以了,预处理出距离,然后就是一个TSP问题了(注意某个源文件是另一个的字串的情况)。

zoj3494,AC自动机+数位DP。注意处理前导0的情况。然后试了一下7k+的数位DP模板,用dfs做,在zoj竟然排到了rank2...。

AC自动机专题总结的更多相关文章

  1. AC自动机专题

    AC自动机简介:KMP是用于解决单模式串匹配问题, AC自动机用于解决多模式串匹配问题. 精华:设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,他的儿子中也有字母为C的节点.然后把当 ...

  2. AC自动机 专题

    // 求目标串中出现了几个模式串 //==================== #include <stdio.h> #include <algorithm> #include ...

  3. 【原创】AC自动机小结

    有了KMP和Trie的基础,就可以学习神奇的AC自动机了.AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配.           AC自动机 其实 就是创建了一个状态的转移图,思想很 ...

  4. AC自动机(AC automation)

    字典树+KMP 参考自: http://www.cppblog.com/mythit/archive/2009/04/21/80633.html ; //字典大小 //定义结点 struct node ...

  5. 转自kuangbin的AC自动机(赛前最后一博)

    有了KMP和Trie的基础,就可以学习神奇的AC自动机了.AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配.           AC自动机 其实 就是创建了一个状态的转移图,思想很 ...

  6. HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430 AC自动机求文本串和模式串信息(模板题)

    最近正在学AC自动机,按照惯例需要刷一套kuangbin的AC自动机专题巩固 在网上看过很多模板,感觉kuangbin大神的模板最为简洁,于是就选择了用kuangbin大神的模板. AC自动机其实就是 ...

  7. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

  8. [专题总结]AC自动机

    其实前面的模板也不是1A,我在题库里提前做过,也不必在意罚时,刚开始我在做别的专题 裸模板我就不说了,各个博客讲解的很明白 void insert(string s){ ,len=s.size(); ...

  9. [专题汇总]AC自动机

    1.The 2011 ACM-ICPC Asia Dalian Regional Contest ZOJ 3545 Rescue the Rabbit  简单的AC自动机+状压DP, 状态DP[nod ...

随机推荐

  1. 【Codeforces629C】Famil Door and Brackets [DP]

    Famil Door and Brackets Time Limit: 20 Sec  Memory Limit: 512 MB Description Input Output Sample Inp ...

  2. 01背包入门 dp

    题目引入: 有n个重量和价值分别为Wi,Vi的物品.从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中的价值总和的最大值. 分析: 首先,我们用最普通的方法,针对每个物品是否放入背包进行搜索. ...

  3. Commonjs,AMD,CMD和UMD的差异

    CommonJS 一种服务器端模块化的规范,Nodejs实现了这种规范,所以就说Nodejs支持CommonJS. CommonJS分为三部分: require 模块加载 exports 模块导出 m ...

  4. css3_box-shadow使用记录

    1.box-shadow这个属性有6个参数可设置,使用的时候比较少用,每次使用的时候都会忘记,故写此文作记录. 样式: /*1.添加此属性添加阴影*/ box-shadow: 0 0 10px 10p ...

  5. Spring Boot:定制自己的starter

    在学习Spring Boot的过程中,接触最多的就是starter.可以认为starter是一种服务——使得使用某个功能的开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由Spring Boo ...

  6. Msfvenom学习总结-MSF反弹webshell

    1.    –p (- -payload-options) 添加载荷payload. 载荷这个东西比较多,这个软件就是根据对应的载荷payload生成对应平台下的后门,所以只有选对payload,再填 ...

  7. 从零开始PHP攻略(000)——关于WAMPServer集成环境

    Apache.PHP和MySQL都可以用于多种操作系统和Web服务器的组合.本篇介绍在Windows下用WampServer环境包来搭建本地php环境. W:windows A:Apache M:My ...

  8. Python学习笔记 - day10 - 正则表达式

    正则表达式 字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在.比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样 ...

  9. Linux汇编教程04:寻址方式

    这一节,我们主要来讨论寻址方式,这一点十分重要. 我们上一节有稍微提了一下,内存地址引用的通用格式: 地址或偏移(%基址寄存器, %索引寄存器, 比例因子 ) 结果地址 = 地址或偏移 + %基址寄存 ...

  10. Linux 入门记录:十八、Linux 系统启动流程 + 单用户修改 root 密码 + GRUB 加密

    一.系统启动流程 一般来说,Linux 系统的启动流程是这样的: 1. 开机之后,位于计算机主板 ROM 芯片上的 BIOS 被最先读取,在进行硬件和内存的校验以及 CPU 的自检没有异常后, BIO ...