[BZOJ2938][POI2000] Virus (AC Automata)

Description

The Binary Virus Review Board recently discovered the following pattern: Certain binary strings are the code for viruses. If a piece of code does not contain any piece of virus code, then we call this piece of code safe. Now that the committee has found all the virus code segments, the question is whether there is an infinitely long safe binary code.

Example: For example, if {011, 11, 00000} is a virus code segment, then a possible infinite security code is 010101…. If {01, 11, 000000} is a virus code segment, then there is no infinite security code. Task: Please write a program: (1) Read the virus code;

(2) Determine whether there is an infinitely long security code;

(3) output the result

Input Format

The first line includes an integer n, which represents the number of virus code segments. Each of the following n lines contains a non-empty 01 string - a virus code segment. The total length of all virus code segments does not exceed 30000.

Output Format

You should output a word in the first line of the text file WIN.OUT: (1) TAK - if such a code exists; (2) NIE - if not.

Solution

Build an AC automaton, merge the fail pointer to the child node, and then form a directed graph,

Then on the graph dfs, if there is a ring, there is an infinitely long string

 

Code

 

#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 30010
using namespace std;

char s[N];
int n,T[N][2],fail[N],cnt=1,q[N];
bool mark [N], fish [N], inq [N];

inline void Insert(){
	scanf("%s\n",s);
	int len=strlen(s),now=1;
	for(int i=0;i<len;++i){
		if(!T[now][s[i]-'0']) T[now][s[i]-'0']=++cnt;
		now=T[now][s[i]-'0'];
	}
	mark[now]=1;
}

inline void getfail(){
	int h=0,t=0,now;q[++t]=1;
	for(int i=0;i<2;++i) T[0][i]=1;
	while(h<t){
		now=q[++h];
		for(int i=0;i<2;++i)			
			if(T[now][i]){
				int k=fail[now];
				while(!T[k][i]) k=fail[k];
				fail[q[++t]=T[now][i]]=T[k][i];
				mark[T[now][i]]|=mark[T[k][i]];
			}else T[now][i]=T[fail[now]][i];	
	}
}

bool dfs(int u){
	inq [u] = 1;
	for(int i=0;i<2;++i){
		int v = T [u] [i];
		if(inq[v]) return 1;
		if(vis[v]||mark[v]) continue;
		force[v]=1;
		if(dfs(v)) return 1;
	}
	inq [u] = 0;
	return 0;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i) Insert();
	getfail();
	dfs(1)?puts("TAK"):puts("NIE");
	return 0;
}

 

 

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326592654&siteId=291194637