P3796 【模板】AC自动机(加强版)
2017-07-06 17:11
337 查看
题目描述
有个由小写字母组成的模式串以及一个文本串
。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串
中出现的次数最多。
输入输出格式
输入格式:输入含多组数据。
每组数据的第一行为一个正整数
,表示共有
个模式串,
。
接下去
行,每行一个长度小于等于
的模式串。下一行是一个长度小于等于
的文本串
。
输入结束标志为
。
输出格式:
对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。
输入输出样例
输入样例#1:2 aba bab ababababac 6 beta alpha haha delta dede tata dedeltalphahahahototatalpha 0
输出样例#1:
4 aba 2 alpha haha
就是个纯模板,没啥好说的,。
不过AC自动机真的是,,恶心到爆,,,
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<map> using namespace std; const int MAXN=100001; void read(int &n) { char c='+';int x=0;bool flag=0; while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;} while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();} flag==1?n=-x:n=x; } char s[MAXN][101]; char text[1000001]; struct AC_Automata { int sz; int ch[MAXN][28];//trie树 int cnt[MAXN];// 每个单词出现的次数 int val[MAXN];// 记录是否有单词 int last[MAXN]; int f[MAXN]; int sigma_sz; map<string,int>mp;//出现的位置 void Init() { memset(ch[0],0,sizeof(ch[0])); memset(cnt,0,sizeof(cnt)); mp.clear(); sz=1; sigma_sz=26; } int idx(char c) { return c-'a'; } void Insert(char *s,int pos) { int l=strlen(s); int now=0; for(int i=0;i<l;i++) { int c=idx(s[i]); if(!ch[now][c]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[now][c]=sz++; } now=ch[now][c]; } val[now]=pos;//一个单词的结束 mp[string(s)]=pos; // 记录这个字符串出现的位置,按顺序输出 } void getfail() { f[0]=0; queue<int>q; for(int i=0;i<sigma_sz;i++) { int u=ch[0][i]; if(u)// 此处有单词出现 { f[u]=0;// 连向根节点 q.push(u); last[u]=0;// 上一个出现的单词一定是根节点 // 上面两条语句没什么卵用,只是为了帮助理解AC自动机的含义 } } while(!q.empty()) { int p=q.front();q.pop(); for(int i=0;i<sigma_sz;i++) { int u=ch[p][i]; if(!u)//没有孩子 { ch[p][i]=ch[f[p]][i];// 补上一条不存在的边,减少查找次数 continue; } q.push(u); int v=f[p];// 找到它的失陪指针 f[u]=ch[v][i];//因为我们在上面补上了一条不存在边,所以他一定存在孩子 last[u]=val[f[u]] ? f[u] : last[f[u]]; //判断下是不是单词结尾 是, 不是 } } } int ok(int pos) { if(pos) { cnt[val[pos]]++; ok(last[pos]); } } void find(char *s)// 查找模式串 { int l=strlen(s); int j=0;// 当前节点的编号 for(int i=0;i<l;i++) { int c=idx(s[i]); while(j&&!ch[j][c]) j=f[j];// 顺着失配边走 j=ch[j][c]; // 取到儿子 if(val[j]) ok(j);// 找到一个单词 else if(last[j]) ok(last[j]);// 当前节点不行就看看上一个单词出现的位置行不行 } } }ac; int n; int main() { while(scanf("%d",&n)==1&&n!=0) { ac.Init(); for(int i=1;i<=n;i++) { scanf("%s",s[i]); ac.Insert(s[i],i); } ac.getfail(); scanf("%s",text); ac.find(text); int ans=-1; for(int i=1;i<=n;i++) if(ac.cnt[i]>ans) ans=ac.cnt[i]; printf("%d\n",ans); for(int i=1;i<=n;i++) if(ac.cnt[i]==ans) printf("%s\n",s[i]); } return 0; }
相关文章推荐
- P3796 【模板】AC自动机(加强版)
- P3796 【模板】AC自动机(加强版)
- cjoj P1435 - 【模板题 USACO】AC自动机 && 洛谷 P3796 【模板】AC自动机(加强版)
- 洛谷 P3796 【模板】AC自动机(加强版)
- 洛谷P3796 【模板】AC自动机(加强版)
- 洛谷 P3796 【模板】AC自动机(加强版)
- 【洛谷P3796】【模板】AC自动机(加强版)
- 【模板】AC自动机(加强版) 洛谷3796 AC自动机
- luogu P3796【模板】AC自动机(加强版)
- [洛谷3796]【模板】AC自动机(加强版)
- 【洛谷】3796 【模板】AC自动机(加强版)
- luogu3796 【模板】AC自动机(加强版)
- luogu3796【模板】AC自动机(加强版)
- 洛谷P3796 - 【模板】AC自动机(加强版)
- 我的ac自动机模板
- HDU2222 AC自动机模板
- hdu 2222 ac自动机模板题
- hdu 3695 AC自动机模板题
- AC自动机算法及模板
- AC自动机模板