bzoj 2938: [Poi2000]病毒 AC自动机
2017-02-20 20:46
489 查看
题意
二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
l 读入病毒代码;
l 判断是否存在一个无限长的安全代码;
l 将结果输出
所有病毒代码段的总长度不超过30000
分析
将所有字符建立AC自动机,若指针能在自动机上找到一个环则TAK。代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; char ch[30005]; int fail[30005],trie[30005][3],n,val[30005],vis[30005],cnt,q[30005],inst[30005]; void ins() { int len=strlen(ch),now=1; for (int i=0;i<len;i++) if (trie[now][ch[i]-'0']) now=trie[now][ch[i]-'0']; else now=trie[now][ch[i]-'0']=++cnt; val[now]=1; } void get_fail() { fail[0]=1; int head=1,tail=1;q[1]=1; while (head<=tail) { int u=q[head]; head++; for (int i=0;i<2;i++) { int v=trie[u][i]; if (!v) { if (u!=1) trie[u][i]=trie[fail[u]][i]; continue; } int k=fail[u]; while (!trie[k][i]) k=fail[k]; fail[v]=trie[k][i];val[v]|=val[trie[k][i]]; q[++tail]=v; } } } bool dfs(int x) { vis[x]=inst[x]=1; for (int i=0;i<2;i++) { if (inst[trie[x][i]]) return 1; if (!trie[x][i]||val[trie[x][i]]||vis[trie[x][i]]) continue; if (dfs(trie[x][i])) return 1; } inst[x]=0; return 0; } int main() { trie[0][0]=trie[0][1]=cnt=1; scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%s",ch); ins(); } get_fail(); if (dfs(1)) printf("TAK"); else printf("NIE"); return 0; }
相关文章推荐
- BZOJ 2938: [Poi2000]病毒 AC自动机
- 【AC自动机】【bzoj 2938】: [Poi2000]病毒
- BZOJ 2938: [Poi2000]病毒 [AC自动机 拓扑排序]
- BZOJ 2938: [Poi2000]病毒 AC自动机
- [BZOJ]2938 [POI2000] 病毒 AC自动机
- bzoj 2938: [Poi2000]病毒(AC自动机)
- BZOJ 2938: [Poi2000]病毒
- 【BZOJ】2938: [Poi2000]病毒
- bzoj 2938: [Poi2000]病毒
- BZOJ 2938: [Poi2000]病毒
- bzoj2938: [Poi2000]病毒
- 【BZOJ】【P2938】【Poi2000】【病毒】【题解】【AC自动机】
- BZOJ2938 & 洛谷2444:[POI2000]病毒——题解
- 【bzoj2938】[Poi2000]病毒 AC自动机
- 【bzoj2938】[Poi2000]病毒 AC自动机
- [bzoj2938][Poi2000]病毒_AC自动机
- [bzoj2938][Poi2000]病毒 AC自动机
- BZOJ 2938 [Poi2000]病毒(AC自动机)
- 【bzoj2938】病毒 AC自动机
- bzoj 2938 病毒 AC自动机