COGS 1913. AC自動機
阿新 • • 發佈:2017-08-14
stdin 題目 rapi fault opened n) pla http lis
★★ 輸入文件: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 <stringAC自動機(指針)> #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自動機