专题训练之AC自动机

推荐博客:http://www.cnblogs.com/kuangbin/p/3164106.html AC自动机小结

https://blog.csdn.net/creatorx/article/details/71100840 AC自动机最详细的解释

1.(HDOJ2222)http://acm.hdu.edu.cn/showproblem.php?pid=2222

题意:求目标串中出现了几个模式串。

分析:AC自动机模板题

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=500010;
  8
  9 struct Trie
 10 {
 11     int nxt[maxn][26],fail[maxn],end[maxn]; //nxt为字典树, fail相当于kmp中的nxt数组, end对单词结尾做标记
 12     int root,L;  //L相当于字典树中的sz ,root为根节点(即;0)
 13     int newnode() //初相当于始化一个字典树上的节点
 14     {
 15         for ( int i=0;i<26;i++ ) nxt[L][i]=-1;
 16         end[L++]=0;
 17         return L-1;
 18     }
 19     void init()
 20     {
 21         L=0;
 22         root=newnode();
 23     }
 24     void insert(char buf[]) //大致于字典树插入过程相同
 25     {
 26         int len=strlen(buf);
 27         int now=root;
 28         for ( int i=0;i<len;i++ )
 29         {
 30             int x=buf[i]-‘a‘;
 31             if ( nxt[now][x]==-1 ) nxt[now][x]=newnode();
 32             now=nxt[now][x];
 33         }
 34         end[now]++; //在单词结尾处做标记
 35     }
 36     void build()  //相当于kmp的操作
 37     {
 38         queue<int>que;
 39         fail[root]=root; //根节点初始化为0(即其本身)
 40         for (int i=0;i<26;i++ )
 41         {
 42             if ( nxt[root][i]==-1 ) nxt[root][i]=root;
 43             else //Trie中已经构建的节点
 44             {
 45                 int x=nxt[root][i];
 46                 fail[x]=root;
 47                 que.push(x);
 48             }
 49         }
 50         while ( !que.empty() )
 51         {
 52             int now=que.front();
 53             que.pop();
 54             for ( int i=0;i<26;i++ )
 55             {
 56                 if ( nxt[now][i]==-1 ) //无后继点
 57                     nxt[now][i]=nxt[fail[now]][i];//类似于kmp中求nxt数组一样
 58                 else //存在下一个节点
 59                 {
 60                     int x=nxt[now][i];
 61                     fail[x]=nxt[fail[now]][i];//失配指针指向他父节点的失配指针的下一个相同字符处
 62                     que.push(x);
 63                 }
 64             }
 65         }
 66     }
 67     int query(char buf[]) //相当于字典树中的访问操作
 68     {
 69         int len=strlen(buf);
 70         int now=root;
 71         int res=0;
 72         for ( int i=0;i<len;i++ )
 73         //沿着整个文本串移动,每移动到一个字符(节点) 时,通过失配指针不断找寻模式串 ,重点为源头,找到一个就将其标记清除
 74         {
 75             now=nxt[now][buf[i]-‘a‘];
 76             int tmp=now;
 77             while ( tmp!=root )
 78             {
 79                 res+=end[tmp];
 80                 end[tmp]=0;
 81                 tmp=fail[tmp];
 82             }
 83         }
 84         return res; //返回单词个数
 85     }
 86     void debug()
 87     {
 88         for ( int i=0;i<L;i++ )
 89         {
 90             printf("%id=%3d,fail=%3d,end=%3d,chi=[",i,fail[i],end[i]);
 91             for ( int j=0;j<26;j++ ) printf("%2d",nxt[i][j]);
 92             printf("]\n");
 93         }
 94     }
 95 };
 96 char buf[maxn*2];
 97 Trie ac;
 98 int main()
 99 {
100     int T,n;
101     scanf("%d",&T);
102     while ( T-- )
103     {
104         scanf("%d",&n);
105         ac.init();
106         for ( int i=0;i<n;i++ )
107         {
108             scanf("%s",buf);
109             ac.insert(buf);
110         }
111         ac.build();
112         scanf("%s",buf);
113         printf("%d\n",ac.query(buf));
114     }
115     return 0;
116 }

AC自动机模板(含解释)

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=500010;
  8
  9 struct Trie
 10 {
 11     int nxt[maxn][26],fail[maxn],end[maxn];
 12     int root,L;
 13     int newnode()
 14     {
 15         for ( int i=0;i<26;i++ ) nxt[L][i]=-1;
 16         end[L++]=0;
 17         return L-1;
 18     }
 19     void init()
 20     {
 21         L=0;
 22         root=newnode();
 23         memset(end,0,sizeof(end));
 24     }
 25     void insert(char buf[])
 26     {
 27         int len=strlen(buf);
 28         int now=root;
 29         for ( int i=0;i<len;i++ )
 30         {
 31             int x=buf[i]-‘a‘;
 32             if ( nxt[now][x]==-1 ) nxt[now][x]=newnode();
 33             now=nxt[now][x];
 34         }
 35         end[now]++;
 36     }
 37     void build()
 38     {
 39         queue<int>que;
 40         fail[root]=root;
 41         for (int i=0;i<26;i++ )
 42         {
 43             if ( nxt[root][i]==-1 ) nxt[root][i]=root;
 44             else
 45             {
 46                 int x=nxt[root][i];
 47                 fail[x]=root;
 48                 que.push(x);
 49             }
 50         }
 51         while ( !que.empty() )
 52         {
 53             int now=que.front();
 54             que.pop();
 55             for ( int i=0;i<26;i++ )
 56             {
 57                 if ( nxt[now][i]==-1 )
 58                     nxt[now][i]=nxt[fail[now]][i];
 59                 else
 60                 {
 61                     int x=nxt[now][i];
 62                     fail[x]=nxt[fail[now]][i];
 63                     que.push(x);
 64                 }
 65             }
 66         }
 67     }
 68     int query(char buf[])
 69     {
 70         int len=strlen(buf);
 71         int now=root;
 72         int res=0;
 73         for ( int i=0;i<len;i++ )
 74         {
 75             now=nxt[now][buf[i]-‘a‘];
 76             int tmp=now;
 77             while ( tmp!=root )
 78             {
 79                 res+=end[tmp];
 80                 end[tmp]=0;
 81                 tmp=fail[tmp];
 82             }
 83         }
 84         return res;
 85     }
 86     void debug()
 87     {
 88         for ( int i=0;i<L;i++ )
 89         {
 90             printf("%id=%3d,fail=%3d,end=%3d,chi=[",i,fail[i],end[i]);
 91             for ( int j=0;j<26;j++ ) printf("%2d",nxt[i][j]);
 92             printf("]\n");
 93         }
 94     }
 95 };
 96 char buf[maxn*2];
 97 Trie ac;
 98 int main()
 99 {
100     int T,n;
101     scanf("%d",&T);
102     while ( T-- )
103     {
104         scanf("%d",&n);
105         ac.init();
106         for ( int i=0;i<n;i++ )
107         {
108             scanf("%s",buf);
109             ac.insert(buf);
110         }
111         ac.build();
112         scanf("%s",buf);
113         printf("%d\n",ac.query(buf));
114     }
115     return 0;
116 }

HDOJ2222

原文地址:https://www.cnblogs.com/HDUjackyan/p/9043255.html

时间: 2024-10-15 20:39:30

专题训练之AC自动机的相关文章

AC自动机专题

AC自动机 1 /* 2 AC自动机模板 3 */ 4 struct AC { 5 int ch[MAXNODE][SIZE], fail[MAXNODE], val[MAXNODE], sz; 6 void init(void) { 7 memset (ch[0], 0, sizeof (ch[0])); 8 sz = 1; val[0] = 0; 9 } 10 int idx(char c) { 11 return c - 'a'; 12 } 13 void insert(char *P)

[dp专题] AC自动机与状态压缩dp的结合

最近做到好几道关于AC自动机与状态压缩dp的结合的题,这里总结一下. 题目一般会给出m个字符串,m不超过10,然后求长度为len并且包含特定给出的字符串集合的字符串个数. 以HDU 4758为例: 把题意抽象为:给出两个字符串,且只包含两种字符 'R'.'D',现在求满足下列条件的字符串个数:字符串长度为(m+n),其中包含n个'D',m个'R'. 如果不用AC自动机来做,这道题还真没法做了,因为不管怎样都找不到正确的dp状态转移方程. 而如果引入AC自动机,把在AC自动机上的结点当做dp的一个

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

有了KMP和Trie的基础,就可以学习神奇的AC自动机了.AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配.           AC自动机 其实 就是创建了一个状态的转移图,思想很重要.           推荐的学习链接: http://acm.uestc.edu.cn/bbs/read.php?tid=4294 http://blog.csdn.net/niushuai666/article/details/7002823 http://hi.baidu.com/nial

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

AC自动机

AC自动机 直接学AC自动机比较难理解,强烈建议先学完KMP和字典树并进行一定的练习后,对于失配指针和字典树构造有一定理解后再来学AC自动机的内容.有关AC自动机的详细介绍可见刘汝佳的<算法竞赛入门经典训练指南>P214. 给你一个字典(包含n个不重复的单词),然后给你一串连续的字符串文本(长为len),问你该文本里面的哪些位置正好出现了字典中的某一个或某几个单词?输出这些位置以及出现的单词. 这个问题可以用n个单词的n次KMP算法来做(效率为O(n*len*单词平均长度)),也可以用1个字典

LA_3942 LA_4670 从字典树到AC自动机

首先看第一题,一道DP+字典树的题目,具体中文题意和题解见训练指南209页. 初看这题模型还很难想,看过蓝书提示之后发现,这实际上是一个标准DP题目:通过数组来储存后缀节点的出现次数.也就是用一颗字典树从后往前搜一发.最开始觉得这种搞法怕不是要炸时间,当时算成了O(N*N)毕竟1e5的数据不搞直接上N*N的大暴力...后来发现,字典树根本跑不完N因为题目限制字典树最多右100层左右. 实际上这道题旧思想和模型来说很好(因为直观地想半天还真想不出来..)但是实际实现起来很简单--撸一发字典树就好了

AC自动机 总结

模板--参考刘汝佳训练指南 /*===============================*按照训练指南写的 \*===============================*/ #include<cstring> #include<queue> #include<cstdio> #include<map> #include<string> using namespace std; const int SIGMA_SIZE = 26; co

每日总结-05-19(AC自动机结束)

今天下午讨论了一下校赛的题,终于最终拍板,把校赛的题目定下来了. 然后今天A掉了4个AC自动机的题目.终于完成了AC自动机专辑里面的15个题.至此AC自动机完全结束. 明天开启线段树专题..... ------------------------------------------------------------------------------------------------------------------------------------ 1,,hdu-2457-DNA re

AC自动机+dp(CodeForces - 86C )

"Multidimensional spaces are completely out of style these days, unlike genetics problems" — thought physicist Woll and changed his subject of study to bioinformatics. Analysing results of sequencing he faced the following problem concerning DNA