| Virus |
| Time limit:1000 ms,Special time limit:2500 ms,Memory limit:32768kb |
| Total submit users:41,Accepted users:23 |
| Problem 10104:No special judgement |
| Problem description |
The binary virus Review Board recently discovered the following rule: Some identified binary strings are virus code. If a piece of code does not contain any piece of virus code, we call it safe. Now the Committee has found all the virus code segments and asked if there is an infinitely long and secure binary code. For example, if {011, 11,000 00} is a virus code segment, then a possible infinite Changan full code is 010101 .... If {01, 11,000 000} is a virus code segment, there is no infinite length of security code. Task: write a program: Read the virus code, judge whether there is an infinitely long security code, and output the result.
|
| Input |
The first line contains an integer N, indicating the number of virus code segments. Each row of N rows below contains a non-null 01 string-A virus code segment. The total length of all virus code segments cannot exceed 30000.
|
| Output |
Output a word: Tak -- if such code exists; NIE -- if it does not exist
|
| Sample Input |
3011100000 |
| Sample output |
NIE |
| Problem Source |
Sdoi
|
| Submit discuss judge status problems ranklist |
Question Link
Http://acm.hnu.cn/online? Action = problem & type = show & id = 10104.
Train of Thought Analysis:
After careful analysis, we will find that if there is a ring on the AC automatic machine and there is no end node of the word on the ring, then we can.
Why not even the end node of a word.
Because next on the AC automatic machine points to a prefix with the longest suffix equal to or equal to the prefix. If the suffix points to the front of the node at the end of the word, this means that there is a prefix before the end node, so there will always be a word node in this ring.
Therefore, when using DFS, you must avoid the end nodes of all words.
As for DFS, what we need to judge is a continuous link, so we use 1 to mark it during deep search, and then mark it as another one during backtracking.
Then 0 is not marked.
In this way, you can find the nodes that are linked to a ring.
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <queue>#define N 105#define maxn 30005using namespace std;typedef long long ll;const int mod = 100000;const char tab = '0';const int max_next = 2;int next[maxn][max_next],fail[maxn],num[maxn],siz;int newnode(){ for(int i=0;i<max_next;i++) next[siz][i]=0; fail[siz]=num[siz]=0; return siz++;}void init(){ siz=0; newnode();}void Insert(char *s,int len){ int p=0; for(int i=0;i<len;i++) { int &x=next[p][s[i]-tab]; p=x?x:x=newnode(); } num[p]++;}void acbuild(){ queue<int>Q; Q.push(0); while(!Q.empty()) { int temp=Q.front(); Q.pop(); for(int i=0;i<max_next;i++) { int v=next[temp][i]; if(v==0)next[temp][i]=next[fail[temp]][i]; else Q.push(v); if(temp!=0)fail[v]=next[fail[temp]][i]; if(num[next[fail[temp]][i]])num[next[temp][i]]++; } }}int vis[maxn];bool dfs(int now){ vis[now]=1; for(int j=0;j<max_next;j++) { if(num[next[now][j]])continue; if(vis[next[now][j]]==1)return true; if(vis[next[now][j]]==0 && dfs(next[now][j]))return true; } vis[now]=-1; return false;}char word[30005];int main(){ int n,L; while(scanf("%d",&n)!=EOF) { init(); for(int i=1;i<=n;i++) { scanf("%s",word); Insert(word,strlen(word)); } acbuild(); memset(vis,0,sizeof vis); bool ans=false; for(int i=0;i<siz;i++) if(!vis[i] && dfs(i)) { ans=true; break; } acdebug(); if(ans)puts("TAK\n"); else puts("NIE\n"); } return 0;}
Hnu 10104 virus (AC automation + DFS)