BZOJ 2938 [Poi2000]病毒(AC自动机)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2938
【题目大意】
给出一些病毒串,问是否存在不包含任何病毒串的无限长的字符串
【题解】
首先我们对病毒串建立AC自动机,如果我们能够在AC自动机上无限跑但是不成功匹配,
说明就存在这样的安全串,我们在AC自动机上做搜索,
若存在不经过match的环,那就是TAK,否则就是NIE。
【代码】
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=30010; namespace AC_DFA{ const int Csize=2; int tot,son[N][Csize],sum[N],fail[N],q[N],match[N]; void Initialize(){ memset(match,0,sizeof(int)*(tot+1)); memset(fail,0,sizeof(int)*(tot+1)); for(int i=0;i<=tot;i++)for(int j=0;j<Csize;j++)son[i][j]=0; tot=0; fail[0]=-1; } inline int Tr(char ch){return ch-'0';} int Insert(char *s){ int x=0; for(int l=strlen(s),i=0,w;i<l;i++){ if(!son[x][w=Tr(s[i])]){ son[x][w]=++tot; }x=son[x][w]; }sum[x]++; return x; } void MakeFail(){ int h=1,t=0,i,j,x=0; for(i=0;i<Csize;i++)if(son[0][i])q[++t]=son[0][i]; while(h<=t)for(x=q[h++],i=0;i<Csize;i++) if(son[x][i]){ fail[son[x][i]]=son[fail[x]][i],q[++t]=son[x][i]; match[son[x][i]]=sum[son[x][i]]?son[x][i]:match[fail[son[x][i]]]; }else son[x][i]=son[fail[x]][i]; } } using namespace AC_DFA; int inq[N],vis[N]; bool dfs(int x){ inq[x]=1; for(int i=0;i<Csize;i++){ int y=son[x][i]; if(inq[y])return 1; if(vis[y]||match[y])continue; vis[y]=1; if(dfs(y))return 1; }inq[x]=0; return 0; } int n; char s[N]; int main(){ Initialize(); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s); Insert(s); }MakeFail(); if(dfs(0))puts("TAK"); else puts("NIE"); return 0; }
愿你出走半生,归来仍是少年