• 【BZOJ2938】【luoguP2444】病毒


    description

    二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

    示例:

    例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。

    任务:

    请写一个程序:

    1.在文本文件WIR.IN中读入病毒代码;

    2.判断是否存在一个无限长的安全代码;

    3.将结果输出到文件WIR.OUT中。


    analysis

    • 对所有模式串建(AC)自动机,然后考虑可行的安全代码在(AC)自动机上的匹配

    • 安全代码若无限长,则必然在(AC)自动机上无限匹配、且不会匹配到失败节点

    • 注意一个节点的(fail)是失败节点,该节点也是,因为(fail)的字符串是该点字符串的后缀

    • 然后在自动机上(dfs)找出一个环,节点经过两次则有解


    code

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    #define MAXN 100005
    #define ll long long
    #define reg register ll
    #define fo(i,a,b) for (reg i=a;i<=b;++i)
    #define fd(i,a,b) for (reg i=a;i>=b;--i)
    
    using namespace std;
    
    ll trie[MAXN][2],fail[MAXN],vis[MAXN];
    bool bz[MAXN],flag[MAXN];
    char s[30005];
    ll n,tot,root;
    queue<ll>q;
    
    inline ll newnode(){++tot,trie[tot][0]=trie[tot][1]=-1;return tot;}
    inline void init(){tot=0,root=newnode();}
    inline void insert(char s[])
    {
    	ll len=strlen(s),now=root;
    	fo(i,0,len-1)
    	{
    		if (trie[now][s[i]-'0']==-1)trie[now][s[i]-'0']=newnode();
    		now=trie[now][s[i]-'0'];
    	}
    	flag[now]=1;
    }
    inline void buildfail()
    {
    	q.push(root),fail[root]=root;
    	while (!q.empty())
    	{
    		ll now=q.front();q.pop();
    		fo(i,0,1)if (trie[now][i]==-1)trie[now][i]=(now==root?root:trie[fail[now]][i]);
    		else flag[trie[now][i]]|=flag[trie[fail[now]][i]],fail[trie[now][i]]=(now==root?root:trie[fail[now]][i]),q.push(trie[now][i]);
    	}
    }
    inline bool dfs(ll x)
    {
    	if (vis[x]==1)return 1;
    	if (vis[x]==-1)return 0;vis[x]=1;
    	fo(i,0,1)if (!flag[trie[x][i]]){if (dfs(trie[x][i]))return 1;}
    	vis[x]=-1;return 0;
    }
    int main()
    {
    	//freopen("P2444.in","r",stdin);
    	scanf("%lld",&n),init();
    	fo(i,1,n)scanf("%s",&s),insert(s);
    	buildfail(),printf(dfs(root)?"TAK
    ":"NIE
    ");
    	return 0;
    }
    
  • 相关阅读:
    Python
    C#中读写INI文件
    C#函数式编程
    TypeScript安装
    finally是否执行?finally何时执行?
    JavaScript对象、JSON对象、JSON字符串的区别
    webjars-jquery的引用
    spring boot 笔记--第三章
    两个常见tomcat警告分析
    JSch 实现 SSH 端口转发
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11822922.html
Copyright © 2020-2023  润新知