[bzoj2938] [Poi2000]病毒
AC自动机。
是否存在无限长的不存在非法子串的串。。。也就是询问trie图上有没有不经过非法点的环。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=30023; 7 int ch[maxn][2],fail[maxn],dl[maxn],tot,next[maxn][2]; 8 bool gg[maxn],u[maxn],ins[maxn],flag; 9 char s[maxn]; 10 int i,j,k,n,m; 11 12 inline void trie(int n){ 13 int now=0,i; 14 for(i=1;i<=n;i++) 15 if(!ch[now][s[i]-48])now=ch[now][s[i]-48]=++tot; 16 else now=ch[now][s[i]-48]; 17 gg[now]=1; 18 } 19 inline void getfail(){ 20 int l=0,r=1,i,j,p,now;dl[1]=0; 21 while(l<r){ 22 now=dl[++l]; 23 for(i=0;i<2;i++)if(ch[now][i]){ 24 dl[++r]=next[now][i]=j=ch[now][i]; 25 for(p=fail[now];p&&!ch[p][i];p=fail[p]); 26 fail[j]=!now?0:ch[p][i]; 27 gg[j]|=gg[fail[j]]; 28 }else{ 29 for(p=fail[now];p&&!ch[p][i];p=fail[p]); 30 next[now][i]=ch[p][i]; 31 } 32 } 33 } 34 void dfs(int x){ 35 if(ins[x]){flag=1;return;} 36 if(u[x])return; 37 ins[x]=u[x]=1; 38 if(!gg[next[x][0]])dfs(next[x][0]); 39 if(flag)return; 40 if(!gg[next[x][1]])dfs(next[x][1]); 41 ins[x]=0; 42 } 43 int main(){ 44 scanf("%d",&n); 45 for(i=1;i<=n;i++) 46 scanf("%s",s+1),trie(strlen(s+1)); 47 getfail(); 48 dfs(0); 49 puts(flag?"TAK":"NIE"); 50 }