1. 程式人生 > >[Luogu P2444] [BZOJ 2938] [POI2000]病毒

[Luogu P2444] [BZOJ 2938] [POI2000]病毒

洛谷傳送門

BZOJ傳送門

題目描述

二進位制病毒審查委員會最近發現瞭如下的規律:某些確定的二進位制串是病毒的程式碼。如果某段程式碼中不存在任何一段病毒程式碼,那麼我們就稱這段程式碼是安全的。現在委員會已經找出了所有的病毒程式碼段,試問,是否存在一個無限長的安全的二進位制程式碼。

示例:

例如如果 { 011 , 11

, 00000 } \{011, 11, 00000\} 為病毒程式碼段,那麼一個可能的無限長安全程式碼就是 010101 010101…
。如果 { 01 , 11 , 000000 } \{01, 11, 000000\} 為病毒程式碼段,那麼就不存在一個無限長的安全程式碼。

任務:

請寫一個程式:

1.在文字檔案WIR.IN中讀入病毒程式碼;

2.判斷是否存在一個無限長的安全程式碼;

3.將結果輸出到檔案WIR.OUT中。

輸入輸出格式

輸入格式:

在文字檔案WIR.IN的第一行包括一個整數 n ( n 2000 ) n(n\le 2000) ,表示病毒程式碼段的數目。以下的 n n 行每一行都包括一個非空的 01 01 字串——就是一個病毒程式碼段。所有病毒程式碼段的總長度不超過 30000 30000

輸出格式:

在文字檔案WIR.OUT的第一行輸出一個單詞:

TAK——假如存在這樣的程式碼;

NIE——如果不存在。

輸入輸出樣例

輸入樣例#1:

3
01 
11 
00000

輸出樣例#1:

NIE

解題分析

一開始ZZ了, 然後發現把 f a i l fail 邊加進來就是 A C AC 自動機上找環…

注意通過fail下傳不能有的單詞的標記。

程式碼如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <queue>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 100500
int cnt, root, n;
int fail[MX], son[MX][2];
bool tag[MX], vis[MX], ins[MX];
char buf[MX];
std::queue <int> q;
void insert()
{
	R int len = std::strlen(buf), now = root, id;
	for (R int i = 0; i < len; ++i)
	{
		id = buf[i] - '0';
		if (!son[now][id]) son[now][id] = ++cnt;
		now = son[now][id];
	}
	tag[now] = true;
}
void build()
{
	R int now;
	if (son[0][0]) q.push(son[0][0]);
	if (son[0][1]) q.push(son[0][1]);
	W (!q.empty())
	{
		now = q.front(); q.pop();
		for (R int i = 0; i < 2; ++i)
		{
			if (son[now][i])
			{
				fail[son[now][i]] = son[fail[now]][i];
				tag[son[now][i]] |= tag[fail[son[now][i]]];
				q.push(son[now][i]);
			}
			else son[now][i] = son[fail[now]][i];
		}
	}
}
void DFS(R int now)
{
	if (ins[now]) puts("TAK"), exit(0);
	if (vis[now]) return;
	vis[now] = ins[now] = true;
	if (!tag[son[now][0]]) DFS(son[now][0]);
	if (!tag[son[now][1]]) DFS(son[now][1]);
	ins[now] = false;
}
int main(void)
{
	scanf("%d", &n);
	W (n--) scanf("%s", buf), insert();
	build();
	DFS(0);
	puts("NIE");
}