Solution
将所有病毒放到trie树上,将父亲-儿子、自己-fail看作有向边
则题目要求求这个图上是否有一个环,使环上的点不是任何一个病毒的终止点(所以要继承fail的标记)
Code
#include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> using namespace std; const int N=3e4+10; char s[N]; int end[N],in[N],vis[N],n,trie[N][2],fail[N],tot; queue <int> q; void add() { int now=0; for(int i=0;s[i];i++) { int wh=s[i]-'0'; if(!trie[now][wh]) trie[now][wh]=++tot; now=trie[now][wh]; } end[now]=true; } void get_fail() { for(int i=0;i<2;i++) if(trie[0][i]) q.push(trie[0][i]); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<2;i++) { int v=trie[u][i]; if(v) q.push(v),fail[v]=trie[fail[u]][i],end[v]|=end[fail[v]]; else trie[u][i]=trie[fail[u]][i]; } } } void dfs(int u) { if(in[u]) { puts("TAK"); exit(0); } if(vis[u] || end[u]) return; vis[u]=in[u]=1; dfs(trie[u][0]),dfs(trie[u][1]); in[u]=0; } int main() { scanf("%d",&n); while(n--) scanf("%s",s),add(); get_fail(),dfs(0); puts("NIE"); return 0; }