AC自动机笔记

AC自动机

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<queue>
 6 #define MAX 100001
 7 #define u(n) (n-‘a‘)
 8 using namespace std;
 9 struct ac{
10     int son[26],fail,sum;
11     void init(){
12         memset(son,0,sizeof(son));
13         sum=0;
14     }
15 }a[500001];
16 queue<int>q;
17 int last[500001],ans=0,n,tot=0,len;
18 char st[1000001],sp[10000][51];
19 void init(){
20     for(char i=‘a‘;i<=‘z‘;i++){
21         if(a[0].son[u(i)]){
22             q.push(a[0].son[u(i)]);
23             a[a[0].son[u(i)]].fail=0;
24         }
25     }
26     while(!q.empty()){
27         for(char i=‘a‘;i<=‘z‘;i++){
28             if(a[q.front()].son[u(i)]){
29                 q.push(a[q.front()].son[u(i)]);
30                 int now=a[q.front()].fail;
31                 while(now&&!a[now].son[u(i)]) now=a[now].fail;
32                 if(a[now].son[u(i)]) a[q.back()].fail=a[now].son[u(i)];
33                 else a[q.back()].fail=0;
34                 if(a[a[q.back()].fail].sum){
35                     last[q.back()]=a[q.back()].fail;
36                 }else{
37                     last[q.back()]=last[a[q.back()].fail];
38                 }
39             }
40         }
41         q.pop();
42     }
43 }
44 void ins(char st[]){
45     int s=0;
46     for(int i=0;i<strlen(st);i++){
47         if(a[s].son[u(st[i])]==0){
48             a[s].son[u(st[i])]=++tot;
49             a[tot].init();
50             s=tot;
51         }else{
52             s=a[s].son[u(st[i])];
53         }
54     }
55     a[s].sum++;
56 }
57 void inc(int now){
58     if(a[now].sum){
59         ans+=a[now].sum;
60         a[now].sum=0;
61     }
62     while(last[now]){
63         ans+=a[last[now]].sum;
64         a[last[now]].sum=0;
65         now=last[now];
66     }
67 }
68 void solution(int len){
69     int now=0;
70     for(int i=0;i<=len;i++){
71         if(a[now].son[u(st[i])]){
72             now=a[now].son[u(st[i])];
73         }else{
74             while(now&&!a[now].son[u(st[i])]) now=a[now].fail;
75             if(a[now].son[u(st[i])]) now=a[now].son[u(st[i])];
76         }
77         inc(now);
78     }
79 }
80 int main(){
81     scanf("%d",&n);
82     a[0].init();
83     a[0].fail=0;
84     for(int i=1;i<=n;i++){
85         scanf("%s",sp[i]);
86         ins(sp[i]);
87     }
88     scanf("%s",st);
89     len=strlen(st);
90     init();
91     solution(len);
92     printf("%d",ans);
93     return 0;
94 }

原文地址:https://www.cnblogs.com/dcdcbigbig/p/8945112.html

时间: 2024-11-10 12:55:06

AC自动机笔记的相关文章

AC自动机 - 学习笔记

AC自动机 ----多个模板的字符串匹配 字典树Trie加上失配边构成 struct ACauto { int ch[MAXN][26]; int size; int f[MAXN],last[MAXN],val[MAXN],cnt[MAXN]; //val用来在字典树中的模板串末尾处标记,标记为模板串的序号(从1开始) //last后缀链接:结点J沿着失配指针往回走时,遇到的下一个单词尾结点. void init()//初始化 { size=1;//字典树中的节点数 memset(ch[0],

AC自动机学习笔记

搞了一晚上AC自动机,发现需要先学trie和kmp……都不会啊..于是又去现学KMP和trie..终于基本看懂AC自动机了. #include <iostream> using namespace std; struct node { int next[26];//每一个节点可以扩展到的字母 int fail;//每一个节点的失配指针 int count;//记录每一个可以构成单词的字符串距根节点的深度 void init()//构造 { memset(next, -1, sizeof(nex

AC自动机--summer-work之我连模板题都做不出

这章对现在的我来说有点难,要是不写点东西,三天后怕是就一无所有了. 但写这个没有营养的blog的目的真的不是做题或提升,只是学习学习代码和理解一些概念. 现在对AC自动机的理解还十分浅薄,这里先贴上目前我看过的文章: 深入理解Aho-Corasick自动机算法 AC 自动机学习笔记 AC自动机相比Trie多了失配边,结点到结点间的状态转移,结点到根的状态转移. 这里fail的定义是:使当前字符失配时跳转到另一段从root开始每一个字符都与当前已匹配字符段某一个后缀完全相同且长度最大的位置继续匹配

暑假集训day9补充(AC自动机)

推荐网站http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机嘛,此AC(aho-corasick)非彼AC(Accepted). 我也不是很会解释 有一题是必须打的hdu2222. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int mn=

ac自动机基础模板(hdu2222)

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, th

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 2896-病毒侵袭(ac自动机)

题意: 给定多个模式串,每给一个母串,输出包含模式串的编号,最后输出包含模式串的母串的数量. 分析: ac自动机模板 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <st

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

hdoj 2896 病毒侵袭(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式:该问题需要静态建树,另外需要对AC自动机的模板加以修改, 对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &