【bzoj2938】[Poi2000]病毒 AC自动机
2018-01-09 19:14
597 查看
Description
二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
l 读入病毒代码;
l 判断是否存在一个无限长的安全代码;
l 将结果输出
Input
第一行包括一个整数n,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。
Output
你应在在文本文件WIN.OUT的第一行输出一个单词:
l TAK——假如存在这样的代码;
l NIE——如果不存在。
Sample Input
3
01
11
00000
Sample Output
NIE
题解
建立AC自动机,一个代码为安全的当且仅当其能在AC自动机上无限匹配。
判断不走danger点是否构成环。
细节:如果一个点失配,且其连向点为danger,则其也为danger
代码
二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
l 读入病毒代码;
l 判断是否存在一个无限长的安全代码;
l 将结果输出
Input
第一行包括一个整数n,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。
Output
你应在在文本文件WIN.OUT的第一行输出一个单词:
l TAK——假如存在这样的代码;
l NIE——如果不存在。
Sample Input
3
01
11
00000
Sample Output
NIE
题解
建立AC自动机,一个代码为安全的当且仅当其能在AC自动机上无限匹配。
判断不走danger点是否构成环。
细节:如果一个点失配,且其连向点为danger,则其也为danger
代码
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<map> #define ll long long #define inf 1000000000 #define mod 1000000007 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } map<pair<int,int>,bool>mp; char s[30005]; int a[300005][2],tot,point[300005],q[300005],n; bool flag,danger[300005],f[300005],vis[300005]; inline void ins() { int now=1,l=strlen(s); for (int i=0;i<l;i++) { int t=s[i]-'0'; if (!a[now][t]) a[now][t]=++tot; now=a[now][t]; } danger[now]++; } inline void acmach() { int Head=0,tail=1; q[1]=1;point[1]=0; while (Head!=tail) { int now=q[++Head]; for (int i=0;i<2;i++) { if (a[now][i]) { point[a[now][i]]=a[point[now]][i]; if (danger[point[a[now][i]]]) danger[a[now][i]]=1; q[++tail]=a[now][i]; } else a[now][i]=a[point[now]][i]; } } } bool dfs(int now) { f[now]=1; for(int i=0;i<2;i++) { int v=a[now][i]; if(f[v])return 1; if(vis[v]||danger[v])continue; vis[v]=1; if(dfs(v))return 1; } f[now]=0; return 0; } int main() { n=read();a[0][0]=a[0][1]=1;tot=1; for (int i=1;i<=n;i++) { scanf("%s",s); ins(); } acmach(); if (dfs(1)) puts("TAK");else puts("NIE"); return 0; }
相关文章推荐
- [bzoj2938][Poi2000]病毒_AC自动机
- BZOJ 2938 [Poi2000]病毒(AC自动机)
- AC自动机【poi2000】bzoj2938 病毒
- bzoj2938 [Poi2000]病毒 ac自动机
- 【bzoj2938】[Poi2000]病毒 AC自动机
- BZOJ2938 POI2000 病毒 补全AC自动机 Trie图判环
- [bzoj2938][Poi2000]病毒 AC自动机
- BZOJ_2938_[Poi2000]病毒_AC自动机
- 【bzoj 2938】病毒(AC自动机)
- [BZOJ]2938 [POI2000] 病毒 AC自动机
- 【bzoj2938】病毒 AC自动机
- 【AC自动机】【bzoj 2938】: [Poi2000]病毒
- [BZOJ2938][POI2000]病毒 做题笔记
- BZOJ 2938: [Poi2000]病毒 AC自动机
- 【BZOJ2938】病毒,AC自动机练习
- [BZOJ 2938][Poi2000]病毒
- bzoj2938 [Poi2000]病毒
- BZOJ 2938 Poi2000 病毒 AC自动机+拓扑排序
- 【bzoj2938】[Poi2000]病毒
- bzoj 2938 病毒 AC自动机