标签:ac自动机
1.题目描述:点击打开链接
2.解题思路:本题利用AC自动机解决。本题给的文本串非常长,但是模板串又多而短,正好适合AC自动机。然而一个问题是如何统计出现的次数。这里直接在print函数中递归统计。《训练指南》上说因为有重复的模板,需要用一个map来索引,但是本题由于已经把所有的模板保存到P数组了,没有这个索引也可以做。
3.代码:
#include<iostream> #include<algorithm> #include<cassert> #include<string> #include<sstream> #include<set> #include<bitset> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<functional> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define me(s) memset(s,0,sizeof(s)) #define rep(i,n) for(int i=0;i<(n);i++) typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; //typedef pair <int, int> P; const int sigma_size=26; const int maxnode=11000; const int maxs=150+10; map<string,int>ms; struct AhoCorasickAutomata { int ch[maxnode][sigma_size]; int val[maxnode]; int f[maxnode]; int cnt[maxnode]; int last[maxnode]; int sz; void init() { sz=1; me(ch[0]);me(cnt); ms.clear(); } int idx(char c){return c-'a';} void insert(char*s,int v) { int u=0,n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { me(ch[sz]); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=v; ms[string(s)]=v; } void print(int j) { if(j) { cnt[val[j]]++; print(last[j]); } } void find(char*T) { int n=strlen(T); int j=0; for(int i=0;i<n;i++) { int c=idx(T[i]); while(j&&!ch[j][c])j=f[j]; j=ch[j][c]; if(val[j])print(j); else if(last[j])print(last[j]); } } void getFail() { queue<int>q; f[0]=0; for(int c=0;c<sigma_size;c++) { int u=ch[0][c]; if(u){f[u]=0;q.push(u);last[u]=0;} } while(!q.empty()) { int r=q.front();q.pop(); for(int c=0;c<sigma_size;c++) { int u=ch[r][c]; if(!u)continue; q.push(u); int v=f[r]; while(v&&!ch[v][c])v=f[v]; f[u]=ch[v][c]; last[u]=val[f[u]]?f[u]:last[f[u]]; } } } }; AhoCorasickAutomata ac; char text[1000001],P[151][80]; int n,T; int main() { while(~scanf("%d",&n)&&n) { ac.init(); for(int i=1;i<=n;i++) { scanf("%s",P[i]); ac.insert(P[i],i); } ac.getFail(); scanf("%s",text); ac.find(text); int best=-1; for(int i=1;i<=n;i++) if(ac.cnt[i]>best)best=ac.cnt[i]; //寻找最大的次数 printf("%d\n",best); for(int i=1;i<=n;i++) if(ac.cnt[i]==best)//输出出现次数等于best的字符串 printf("%s\n",P[i]); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:ac自动机
原文地址:http://blog.csdn.net/u014800748/article/details/48051679