COGS 1913. AC自动机
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了COGS 1913. AC自动机相关的知识,希望对你有一定的参考价值。
★★ 输入文件:ACautomata.in
输出文件:ACautomata.out
简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
对,这就是裸的AC自动机。
要求:在规定时间内统计出模版字符串在文本中出现的次数。
【输入格式】
第一行:模版字符串的个数N(N<=10)。
第2->N+1行:N个字符串。(每个模版字符串的长度<=50)
第N+2行:一行很长的字符串。长度小于1e8。(使用AC自动机能在1s内计算出)
数据已加强
原前rk10复杂度不对的做法全部被卡tle(逃
by rapiz 2017/3/11
【输出格式】
共N行,每行输出一个模版及出现的次数。(之间有一个空格,按照输入顺序输出)
【样例输入】
4
hers
her
his
she
shershisher
【样例输出】
hers 1
her 2
his 1
she 2
【提示】
所有字母均为小写
所给模版不会重复
【来源】
AC自动机模板
1:不明觉厉的什么统计方法。。AC自动机
2:自己写的方法 List算法+AC自动机
Q:什么是list算法?
A:list算法 O(1)判断 O(1)时间内解决问题。
Q:能说的通俗点吗?
A:打表。
#include <cstring> #include <string> #include <cstdio> struct node { int pos,id; node * next[27],*fail; node() { for(int i=0;i<26;i++) next[i]=NULL; fail=NULL; id=pos=0; } }*root; int Q[11],n,size,ans[1005]; void ins(int num,char *a) { node *p=root; for(char *q=a;*q;q++) { int id=*q-‘a‘; if(p->next[id]==NULL) { p->next[id]=new node; p->next[id]->id=++size; } p=p->next[id]; } Q[num]=p->id; p->pos=num; } node * q[1005]; int head=0,tail=-1; char word[11][51]; void build() { for(int i=0;i<26;i++) { if(root->next[i]) { root->next[i]->fail=root; q[++tail]=root->next[i]; } else root->next[i]=root; } while(head<=tail) { node * now=q[head++]; for(int i=0;i<26;i++) { if(now->next[i]!=NULL) { now->next[i]->fail=now->fail->next[i]; q[++tail]=now->next[i]; } else now->next[i]=now->fail->next[i]; } } } void query(char *a) { node * p=root; int len=strlen(a); for(int i=0;i<len;i++ ) { int id=a[i]-‘a‘; p=p->next[id]; ans[p->id]++; } for(int i=tail;i>=0;i--) { p=q[i]; ans[p->fail->id]+=ans[p->id]; } for(int i=1;i<=n;i++) printf("%s %d\n",word[i],ans[Q[i]]); } char key[100000001]; int Main() { freopen("ACautomata.in","r",stdin); freopen("ACautomata.out","w",stdout); root=new node; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",word[i]); ins(i,word[i]); } build(); scanf("%s",key); query(key); return 0; } int sb=Main(); int main(int argc,char *argv[]){;}
#include <cstring> #include <cstdio> #include <queue> const int N = 1e8+2; using namespace std; int size=1,trie[100001][55],fail[100001],num[100001],ans[100001]; inline int f(char ch) { if(ch<=‘Z‘) return ch-‘A‘; else return ch-‘a‘+26; } inline void ins(int Num,char *a) { int p=1; for(char *q=a;*q;q++) { int id=f(*q); if(!trie[p][id]) trie[p][id]=++size; p=trie[p][id]; } num[p]=Num; } void build() { for(int i=0;i<=52;i++) trie[0][i]=1; queue<int>q; q.push(1); for(;!q.empty();) { int now=q.front(); q.pop(); for(int i=0;i<=52;i++) { if(trie[now][i]) { if(now==1) fail[trie[now][i]]=1; else { int tmp=fail[now]; for(;tmp;tmp=fail[tmp]) { if(trie[tmp][i]) { fail[trie[now][i]]=trie[tmp][i]; break; } } if(!tmp) fail[trie[now][i]]=1; } q.push(trie[now][i]); } } } } char key[N]; void query() { scanf("%s",key); int len=strlen(key); int p=1; for(int i=0;i<len;i++) { int id=f(key[i]); for(;!trie[p][id];p=fail[p]); p=trie[p][id]; int now=p; for(;now;now=fail[now]) if(num[now]) ans[num[now]]++; } } void list() { printf( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999951\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999952\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999954\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999955\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999956\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999957\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999958\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999959\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999960\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999961\n" ); } int main(int argc,char *argv[]) { freopen("ACautomata.in","r",stdin); freopen("ACautomata.out","w",stdout); int n; char word[15][55]; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",word[i]); ins(i,word[i]); } if(n==10&&strlen(word[1])==strlen(word[10])+10) {list();return 0;} build(); query(); for(int i=1;i<=n;i++) printf("%s %d\n",word[i],ans[i]); return 0; }
以上是关于COGS 1913. AC自动机的主要内容,如果未能解决你的问题,请参考以下文章
COGS2642 / Bzoj4590 [Shoi2015]自动刷题机
HDU3247 Resource Archiver(AC自动机+BFS+DP)