2938: [Poi2000]病毒
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1111 Solved: 556
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
01
11
00000
Sample Output
/* 首先我们把所有串建一个AC自动机 方便起见我们直接把fail指针合并到子结点 如果一个串能无限长,也就是说它可以在AC自动机上一直进行匹配但就是匹配不上 也就是说匹配指针不能走到val为1的结点,设这个点为x 即root..x是一个病毒串 那么fail指针指向x的y也不能走 因为root..x是root..y的一个后缀 处理出来判断有向图是否有环 dfs即可 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define maxn 30010 int n,sz=1,a[maxn][2],fail[maxn],word[maxn]; bool ins[maxn],vis[maxn]; char s[maxn]; void insert(){ int now=1,len=strlen(s); for(int i=0;i<len;i++){ int t=s[i]-'0'; if(!a[now][t])a[now][t]=++sz; now=a[now][t]; } word[now]=1; } void acmach(){ queue<int>q; q.push(1);fail[1]=0; while(!q.empty()){ int now=q.front();q.pop(); for(int i=0;i<2;i++){ if(!a[now][i]){a[now][i]=a[fail[now]][i];continue;} int k=fail[now]; while(!a[k][i])k=fail[k]; fail[a[now][i]]=a[k][i]; word[a[now][i]]|=word[a[k][i]]; q.push(a[now][i]); } } } bool dfs(int x){//判断是否有环 ins[x]=1; for(int i=0;i<2;i++){ if(ins[a[x][i]])return 1; if(vis[a[x][i]]||word[a[x][i]])continue; vis[a[x][i]]=1; if(dfs(a[x][i]))return 1; } ins[x]=0; return 0; } int main(){ for(int i=0;i<2;i++)a[0][i]=1; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s); insert(); } acmach(); if(dfs(1))printf("TAK"); else printf("NIE"); return 0; }