【題解】P3796【模板】AC自動機(加強版)
阿新 • • 發佈:2019-02-09
tps mat turn 另一個 lin esp max pac org
【題解】P3796 【模板】AC自動機(加強版)
記錄當前\(cnt\)是第幾個"星"。記錄第幾個串是對應著第幾個星。
這裏補充一點對於\(AC\)自動機的理解。可能一直有個問題我沒有想明白,就是打標記的點只有一個,然而匹配時,假若一個分支包括了另一個不同的分支該怎麽辦。實際上,我們可以在匹配的時候使用\(fail\)數組進行類似鏈式前向星的遍歷,從而遍歷到那個打標記的地方。那麽問題來了,怎麽保證鏈式前向星會遍歷到那個打了標記的節點呢?答案就在\(gen\_fail\)的玄機裏。\(gen\_fail\)時,由於是找和已經匹配部分相同的後綴,所以指向的節點它到\(0\)的長度會越來越小。顯然那個有標記點的串是相較其它包括它自己的串中最短的,那麽一定會被這個鏈式前向星遍歷到。
上代碼
#include<bits/stdc++.h> using namespace std; #define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t) #define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t) #define ERP(t,a) for(register int t=head[a];t;t=e[t].nx) #define Max(a,b) ((a)<(b)?(b):(a)) #define Min(a,b) ((a)<(b)?(a):(b)) #define midd register int mid=(l+r)>>1 #define TMP template < class ccf > TMP inline ccf qr(ccf b){ char c=getchar(); int q=1; ccf x=0; while(c<48||c>57) q=c==45?-1:q,c=getchar(); while(c>=48&&c<=57) x=x*10+c-48,c=getchar(); return q==-1?-x:x; } const int maxn=155; struct AC{ int fail; int son[27]; int cnt; inline int& operator [](int x){ return son[x]; } inline int& operator [](char x){ return son[x-‘a‘+1]; } }ac[maxn*70]; string x[maxn]; int toac[maxn]; int acnt[maxn]; int macnt[maxn]; int act; int prcnt; int n; inline int build(string p,int len){ register int now=0; RP(t,0,len-1){ if(!ac[now][p[t]]) ac[now][p[t]]=++act; now=ac[now][p[t]]; } if(!ac[now].cnt) ac[now].cnt=++prcnt; return ac[now].cnt; } queue < int > q; inline void gen(){ RP(t,1,26){ if(ac[0][t]) q.push(ac[0][t]); } while(!q.empty()){ register int now=q.front(); q.pop(); RP(t,1,26){ if(ac[now][t]) ac[ac[now][t]].fail=ac[ac[now].fail][t],q.push(ac[now][t]); else ac[now][t]=ac[ac[now].fail][t]; } } } inline void match(string p,int len){ register int now=0; RP(t,0,len-1){ now=ac[now][p[t]]; for(register int i=now;i;i=ac[i].fail){ if(ac[i].cnt) macnt[ac[i].cnt]++; } } } int main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif while( (n=qr(1)) ){ memset(ac,0,sizeof ac); memset(macnt,0,sizeof macnt); act=prcnt=0; RP(t,1,n){ cin>>x[t]; toac[t]=build(x[t],x[t].length()); } gen(); cin>>x[0]; match(x[0],x[0].length()); register int ans=0; RP(t,1,prcnt) ans=Max(ans,macnt[t]); cout<<ans<<endl; RP(t,1,n) if(macnt[toac[t]]==ans) cout<<x[t]<<endl; } return 0; }
【題解】P3796【模板】AC自動機(加強版)