bzoj1195 神奇的ac自动机+状态压缩dp
/*
难的不是ac自动机,是状态压缩dp
之前做了一两题类似题目,感觉理解的还不够透彻
*/
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int mxn=605; int L1[mxn*(1<<12)],L2[mxn*(1<<12)]; queue<int>q1,q2; bool vis[mxn][(1<<12)]; int n; int ans[mxn],num=0; struct ACa{ int t[mxn][26]; int fail[mxn]; int end[mxn]; int S,cnt; int q[670],hd,tl; void init(){S=cnt=1;memset(end,0,sizeof end);return;} void insert(char *s,int id){ int len=strlen(s),now=S; for(int i=0;i<len;i++){ if(!t[now][s[i]-'A'])t[now][s[i]-'A']=++cnt; now=t[now][s[i]-'A']; } end[now]|=(1<<id); } void Build(){ hd=1;tl=0; for(int i=0;i<26;i++) if(t[S][i]){q[++tl]=t[S][i];fail[t[S][i]]=S;} else t[S][i]=S; while(hd<=tl){ int u=q[hd++]; int v,r; for(int i=0;i<26;i++){ if(t[u][i]){ fail[t[u][i]]=t[fail[u]][i]; end[t[u][i]]|=end[t[fail[u]][i]]; q[++tl]=t[u][i]; } else t[u][i]=t[fail[u]][i]; } } return; } void solve(){ hd=1;tl=1;int ed=(1<<n)-1; q1.push(S),q2.push(0); while(hd<=tl){ int u=q1.front();q1.pop(); int e=q2.front();q2.pop(); // printf(" e:%d\n",e); if(e==ed){//结束状态 for(;hd>1;hd=L2[hd]){ans[++num]=L1[hd];} for(int i=num;i;i--)printf("%c",ans[i]+'A'); return; } for(int i=0;i<26;i++){ if(!vis[t[u][i]][e|end[t[u][i]]]){ L1[++tl]=i; L2[tl]=hd; q1.push(t[u][i]); q2.push(e|end[t[u][i]]); vis[t[u][i]][e|end[t[u][i]]]=1; } } hd++; } } }ac; char s[60]; int main(){ int i,j; scanf("%d",&n); ac.init(); for(i=0;i<n;i++)scanf("%s",s),ac.insert(s,i); // for(i=1;i<=ac.cnt;i++)if(ac.end[i])printf("%d %d\n",i,ac.end[i]); ac.Build(); ac.solve(); return 0; }