zoukankan      html  css  js  c++  java
  • bzoj2938【Poi2000】病毒

    2938: [Poi2000]病毒

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 345  Solved: 176
    [Submit][Status][Discuss]

    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

    HINT

    Source




    这道题的思路非常好

    首先我们跑一次AC自己主动机。Trie树和失配边就构成了一个有向图。那么,能找到一个无限长的安全代码,当且仅当在非单词节点中存在环。用拓扑排序推断就可以。





    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define F(i,j,n) for(int i=j;i<=n;i++)
    #define D(i,j,n) for(int i=j;i>=n;i--)
    #define ll long long
    #define pa pair<int,int>
    #define maxn 30100
    #define inf 1000000000
    using namespace std;
    struct edge_type
    {
    	int next,to;
    }e[maxn*2];
    int go[maxn],in[maxn],head[maxn],t[maxn][2];
    int n,tot=1,cnt=0;
    bool v[maxn];
    char s[maxn];
    inline void add_edge(int x,int y)
    {
    	e[++cnt]=(edge_type){head[x],y};
    	head[x]=cnt;
    }
    inline void insert()
    {
    	scanf("%s",s);
    	int len=strlen(s),now=1;
    	F(i,0,len-1)
    	{
    		int x=s[i]-'0';
    		if (!t[now][x]) t[now][x]=++tot;
    		now=t[now][x];
    	}
    	v[now]=true;
    }
    inline void bfs()
    {
    	queue<int> q;
    	q.push(1);
    	while (!q.empty())
    	{
    		int x=q.front(),y,j;q.pop();v[x]|=v[go[x]];
    		F(i,0,1)
    		{
    			j=go[x];
    			while (j&&!t[j][i]) j=go[j];
    			if (t[x][i])
    			{
    				go[y=t[x][i]]=j?t[j][i]:1;
    				q.push(y);
    			}
    			else t[x][i]=j?

    t[j][i]:1; } } } inline bool topsort() { queue<int> q; int sum=0; F(i,1,tot) { if (v[i]) sum++; else F(j,0,1) if (!v[t[i][j]]) { add_edge(i,t[i][j]); in[t[i][j]]++; } } F(i,1,tot) if (!v[i]&&!in[i]) q.push(i); while (!q.empty()) { int x=q.front();q.pop();sum++; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; in[y]--; if (!in[y]) q.push(y); } } return sum==tot; } int main() { scanf("%d",&n); F(i,1,n) insert(); bfs(); printf("%s ",topsort()?

    "NIE":"TAK"); return 0; }



  • 相关阅读:
    UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)
    UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)
    【Same Tree】cpp
    【Recover Binary Search Tree】cpp
    【Binary Tree Zigzag Level Order Traversal】cpp
    【Binary Tree Level Order Traversal II 】cpp
    【Binary Tree Level Order Traversal】cpp
    【Binary Tree Post order Traversal】cpp
    【Binary Tree Inorder Traversal】cpp
    【Binary Tree Preorder Traversal】cpp
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6952256.html
Copyright © 2011-2022 走看看