Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 254|回复: 0

[默认分类] Luogu P2444 病毒___AC自动机+dfs

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-3-15 13:31:32 | 显示全部楼层 |阅读模式
    题目大意:

    有N个确定的二进制串是病毒的代码。当某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

    n≤2000
    所有病毒代码段的总长度不超过30000

    题解:

    将所有的病毒代码构建一个AC自动机,
    如果存在一个可行解,必定它在trie树中,从根节点开始走,不会碰到所有病毒的末尾节点(即不可行的点)。
    而一个点,显然它的fail边连的点不可行,则这个点也必定是不可行的。
    那么我们可以从trie的根节点进行dfs,
    注意不走危险节点,不走历史访问过而已经不在栈中的节点
    记录每个节点在当前 dfs 走的路径上有没有被选中,注意要保证路径上的点不存在不可行节点
    当路径中出现环,则有解

    代码:
    #include<bits/stdc++.h>
    #define N 233333

    using namespace std;  

    int n,num,next[N][2],fail[N],end[N],vis[N],rp[N];  
    char s[N];

    void insert(char *s)
    {
         int len=strlen(s);
         int u=0;
         for (int i=0; i<len; i++)
             {
                  int v=s[i]-'0';
                  if (!next[u][v]) next[u][v]=++num;
                  u=next[u][v];
             }
         end[u]=1;
    }
    void build()  
    {  
         queue <int> Q;
         for (int i=0; i<=1; i++)  
              if (next[0][i]) Q.push(next[0][i]);  
         while (!Q.empty())  
               {  
                   int u=Q.front();
                   Q.pop();  
                   for (int i=0; i<=1; i++)  
                       if (!next[u][i])
                           next[u][i]=next[fail[u]][i];   
                       else {
                                end[next[u][i]]|=end[next[fail[u]][i]];  
                                fail[next[u][i]]=next[fail[u]][i];  
                                Q.push(next[u][i]);  
                            }
               }      
    }  

    bool dfs(int dep)  
    {  
        vis[dep]=rp[dep]=1;  
        for(int i=0; i<=1; i++)  
            {
                if (rp[next[dep][i]]) return 1;
                if (!end[next[dep][i && !vis[next[dep][i && dfs(next[dep][i])) return 1;  
            }
        rp[dep]=0;  
        return 0;  
    }  

    int main()  
    {  
        scanf("%d",&n);  
        for (int i=1; i<=n; i++)
            {  
                 scanf("%s",s);
                 insert(s);  
            }  
        build();  
        if (dfs(0)) printf("TAK");
               else printf("NIE");
        return 0;  
    }  
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-16 13:43 , Processed in 0.386538 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表