复杂度:

查找O(n),维护O(n)

概要:

应用了kmp的自匹配思想,在trie建图时维护一个fali指针,指向上一个匹配的点,这点是用bfs做到。匹配串的时候同样没匹配到就和kmp一样返回。

应用:单串匹配多模板,维护多模板里边的信息。

技巧及注意:

插入和trie一样,然后是bfs。

在bfs的过程中,注意以根开头的不需要匹配fail,即ch[0][i]不需要匹配他们的fail,即为空。

然后在查找的时候当找到一个时我们要遍历这个节点的整个fail树,然后取出信息后记得将信息清空。

一定要注意!节点数是不超过n个串的总长度!!!一定要切记!!!

注意!!bfs的时候一定要维护信息!!!!

例题:

  1. 【BZOJ】1030: [JSOI2007]文本生成器(递推+ac自动机)(将自动机的节点作为转移的状态然后递推)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } using namespace std; const int N=10000000, Type=26;
int T[N][Type], w[N], fail[N], cnt, q[N], front, tail, ans;
char str[1000000], st[1000000]; inline void ins(char s[]) {
int len=strlen(s), now=0;
rep(i, len) {
int t=s[i]-'a';
if(!T[now][t]) T[now][t]=++cnt;
now=T[now][t];
}
++w[now];
}
void bfs() {
int now=0;
q[tail++]=0;
while(tail!=front) {
now=q[front++]; if(front==N) front=0;
rep(i, 26) if(T[now][i]) {
q[tail++]=T[now][i]; if(tail==N) tail=0;
if(now==0) continue;
int p=fail[now];
while(p && !T[p][i]) p=fail[p];
fail[T[now][i]]=T[p][i];
}
}
}
void ac(char s[]) {
int len=strlen(s), now=0;
rep(i, len) {
int t=s[i]-'a';
while(now && !T[now][t]) now=fail[now];
now=T[now][t];
t=now;
while(t) {
ans+=w[t];
w[t]=0;
t=fail[t];
}
}
}
int main() {
scanf("%s", str);
int n=getint();
while(n--) {
scanf("%s", st);
ins(st);
}
bfs();
ac(str);
print(ans);
return 0;
}

没错,就是AC自动机!(可惜不像金坷垃那样~)

不多说,放上模板,不难理解的。

#include <cstdio>
#include <cstring>
#include <queue>
#define for1(i,a,n) for(i=a;i<=n;++i)
#define for2(i,a,n) for(i=a;i<n;++i)
#define for3(i,a,n) for(i=n;i>=a;--i)
#define for4(i,a,n) for(i=n;i>a;--i)
#define CC(i,a) memset(i, a, sizeof(i)) using namespace std; const int N=10000000, Type=26;
char a[N], b[N];
int ch[N][Type], fail[N], w[N], ans, cnt=1;
queue<int> q; void ins(char* s) {
int u=0, v, i, len=strlen(s);
for2(i, 0, len) {
v=s[i]-'a';
if(!ch[u][v]) ch[u][v]=cnt++;
u=ch[u][v];
}
w[u]++;
} void bfs() {
fail[0]=0;
q.push(0);
int u, p, i;
while(!q.empty()) {
u=q.front(); q.pop();
for2(i, 0, Type) if(ch[u][i]) {
q.push(ch[u][i]); //先插入,后判断
if(!u) continue; //不要在这里错了。。
p=fail[u];
while(p && !ch[p][i]) p=fail[p];
fail[ch[u][i]]=ch[p][i];
}
}
} void ac(char* s) {
int i, u=0, v, len=strlen(s), t;
for2(i, 0, len) {
v=s[i]-'a';
while(u && !ch[u][v]) u=fail[u];
u=ch[u][v];
t=u;
while(t) {
ans+=w[t];
w[t]=0;
t=fail[t];
}
} } void init() {
CC(fail, 0);
CC(ch, 0);
CC(w, 0);
} int main() {
init();
scanf("%s", a);
int n, i;
scanf("%d", &n);
for1(i, 1, n) {
scanf("%s", b);
ins(b);
}
bfs();
ac(a);
printf("%d\n", ans); return 0;
}

注意一些细节即可

小结:ac自动机的更多相关文章

  1. AC自动机学习小结

    AC自动机 简要说明 \(AC\) 自动机,全称 \(Aho-Corasick\ automaton\) ,是一种有限状态自动机,应用于多模式串匹配.在 \(OI\) 中通常搭配 \(dp\) 食用. ...

  2. AC自动机详解 (P3808 模板)

    AC自动机笔记 0.0 前言 哇,好久之前就看了 KMP 和 Trie 树,但是似乎一直没看懂 AC自动机?? 今天灵光一闪,加上之前看到一些博客和视频,瞬间秒懂啊... 其实这个玩意还是蛮好理解的. ...

  3. AC自动机fail树小结

    建议大家学过AC自动机之后再来看这篇小结 fail树就是讲fail指针看做一条边连成的树形结构 fail指针在AC自动机中的含义是指以x为结尾的后缀在其他模式串中所能匹配的最长前缀的长度 所以在模式串 ...

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

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

  5. AC自动机小结

    专题链接 第一题--hdu2222 Keywords Search ac自动机的模板题,入门题.  题解 第二题--hdu2896 病毒侵袭   一类病毒的入门题,类似模板  题解 第三题--hdu3 ...

  6. AC自动机算法小结

    AC自动机,可惜不能自动AC 转载:飘过的小牛 OIer55242 简介 Aho-Corasick automation 该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就 ...

  7. 【专题】字符串专题小结(AC自动机 + 后缀自动机)

    AC自动机相关: $fail$树: $fail$树上以最长$border$关系形成父子关系,我们定一个节点对应的串为根到该节点的路径. 对于任意一个非根节点$x$,定$y = fa_{x}$,那$y$ ...

  8. AC自动机 & Fail树 专题练习

    Fail树就是AC自动机建出来的Fail指针构成的树. [bzoj3172][xsy1713]单词 题意 给定一些单词,求每个单词在所有单词里面的出现次数. 分析 构建Fail树,记录每个单词最后一个 ...

  9. Aho-Corasick automaton(AC自动机)解析及其在算法竞赛中的典型应用举例

    摘要: 本文主要讲述了AC自动机的基本思想和实现原理,如何构造AC自动机,着重讲解AC自动机在算法竞赛中的一些典型应用. 什么是AC自动机? 如何构造一个AC自动机? AC自动机在算法竞赛中的典型应用 ...

随机推荐

  1. asp.net动态输出透明gif图片

    要使用asp.net动态输出透明gif图片,也就是用Response.ContentType = "image/GIF". 查了国内几个中文资料都没解决,最后是在一个英文博客上找到 ...

  2. Android ViewPager轮播图

    Android客户端开发中很多时候需要用到轮播图的方式进行重点新闻的推送或者欢迎页面的制作,下面这个轮播图效果的Deamo来自互联网再经过修改而成. 1.布局文件activity_main.xml中添 ...

  3. codeforces 485A.Factory 解题报告

    题目链接:http://codeforces.com/problemset/problem/485/A 题目意思:给出 a 和 m,a 表示第一日的details,要求该日结束时要多生产 a mod ...

  4. hdu 1879 继续畅通工程 解题报告

    题目链接:http://code.hdu.edu.cn/showproblem.php?pid=1879 这条题目我的做法与解决Constructing Roads的解法是相同的. 0 表示没有连通: ...

  5. mysql如何利用Navicat 导出和导入数据库

    MySql是我们经常用到的数据,无论是开发人员用来练习,还是小型私服游戏服务器,或者是个人软件使用,都十分方便.对于做一些个人辅助软件, 选择mysql数据库是个明智的选择,有一个好的工具更是事半功倍 ...

  6. 一、HTML和CSS基础--开发工具--Sublime前端开发工具技巧介绍

    下载:官网下载(根据系统下载) 安装:按步骤安装即可 注意:当前稳定版本为2,但3的功能有提升:Mac和Windows下的快捷键不同 优点:启动速度快,界面简洁,可以直接打开图片. 1 菜单栏主要功能 ...

  7. Primace 5.0软件与KEIL单片机软件联合在线仿真步骤

    Primace 软件是CME(京微雅格)公司的FPGA芯片开发专用软件.因为CME的FPGA,如M5.M7等内嵌有8051核,所以可以和MCU联合在线仿真,虽然FPGA内的程序不可控,不能一步一步的仿 ...

  8. JS输入框邮箱自动提示(带有demo和源码)(转载)

    今天在javascriptQQ群里面 有童鞋问到 有没有 "JS输入框邮箱自动提示"插件,即说都找遍了github上源码 都没有看到这样类似的插件,然后我想了下 "JS输 ...

  9. hrbustoj 1179:下山(DFS+剪枝)

    下山Time Limit: 1000 MS Memory Limit: 65536 KTotal Submit: 271(111 users) Total Accepted: 129(101 user ...

  10. Java Hour 21 Weather

    有句名言,叫做10000小时成为某一个领域的专家.姑且不辩论这句话是否正确,让我们到达10000小时的时候再回头来看吧. 本文作者Java 现经验约为21 Hour,请各位不吝赐教. 继续心情不佳,那 ...