您的位置:首页 > 编程语言

BZOJ2938 POI2000 病毒 题解&代码

2016-03-11 16:45 330 查看
题意:给出n个病毒代码,判断是否有无限长度的代码满足:不包含任何病毒代码。

题解:

看到多字符串匹配,就想到AC自动机【这语气好奇怪

AC自动机建好fail指针,然后从根向下dfs查找,所有实节点都用flag标记,如果找到了一个不经过病毒路径的环,那么就存在无限长度代码满足不包含任何病毒代码

/**************************************************************
Problem: 2938
User: Rainbow6174
Language: C++
Result: Accepted
Time:52 ms
Memory:2128 kb
****************************************************************/

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 30005;
int n, tot, ch[maxn][2], fail[maxn], danger[maxn], q[maxn], flag, temp, vis[maxn], e[maxn];
char s[maxn];
void addtrie(char s[])
{
int x = 0, p = 0, len = strlen(s);
while( p < len )
{
temp = s[p]-'0';
if( !ch[x][temp] ) ch[x][temp]=++tot;
x = ch[x][temp];
p++;
}
danger[x] = 1;
}
void AC(void)
{
int h = 0, t = 0;
for(int i = 0; i < 2; i++)
if(ch[0][i]) q[t++] = ch[0][i];
while( h < t )
{
temp = q[h++];
for(int i = 0; i < 2; i++)
{
if(!ch[temp][i]) ch[temp][i] = ch[fail[temp]][i];
else
{
fail[ch[temp][i]] = ch[fail[temp]][i];
danger[ch[temp][i]] |= danger[ch[fail[temp]][i]];
q[t++] = ch[temp][i];
}
}
}
}
void dfs(int x)
{
if(flag) return;
if(x) vis[x] = 1;
for(int i = 0; i < 2; i++)
{
int v = ch[x][i];
if(vis[v])
{
flag = 1;
return;
}
if(e[v] || danger[v])continue;
e[v] = 1;
dfs(v);
}
vis[x] = 0;
}
int main(void)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%s", s);
addtrie(s);
}
AC();
dfs(0);
if(flag) printf("TAK\n");
else printf("NIE\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: