zoukankan      html  css  js  c++  java
  • [AC自动机]luogu P2444 病毒

    https://www.luogu.org/problem/P2444

    分析

    手玩样例可以发现一个无限长的安全串放到危险代码的AC自动机中匹配,一定会成环

    将fail也视为一条单向边,DFS跑个不经过任何代码结尾的环即可

    特殊的,如果一个点的fail指向一个代码的结尾,那么这个节点也是危险的(这个串的最长公共后缀是个危险代码)

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int N=3e4+10;
    int fail[N],c[N][2],f[N],cnt=0;
    bool vis[N],end[N],ok;
    string s;
    int n;
    
    void Insert(string s) {
        int len=s.length(),x=0;
        for (int i=0;i<len;i++) {
            if (!c[x][s[i]-48]) f[c[x][s[i]-48]=++cnt]=x;
            x=c[x][s[i]-48];
        }
        end[x]=1;
    }
    
    void Build() {
        queue<int> q;
        while (!q.empty()) q.pop();
        if (c[0][0]) q.push(c[0][0]);
        if (c[0][1]) q.push(c[0][1]);
        while (!q.empty()) {
            int u=q.front();q.pop();
            end[u]|=end[fail[u]];
            for (int i=0;i<2;i++)
                if (c[u][i]) {
                    q.push(c[u][i]);
                    fail[c[u][i]]=c[fail[u]][i];
                }
                else c[u][i]=c[fail[u]][i];
        }
    }
    
    void DFS(int u) {
        if (end[u]) return;
        if (vis[u]) {
            printf("TAK
    ");ok=1;
            return;
        }
        vis[u]=1;
        if (c[u][0]) DFS(c[u][0]);
        if (ok) return;
        if (c[u][1]) DFS(c[u][1]);
        if (ok) return;
        vis[u]=0;
    }
    
    int main() {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) {
            cin>>s;
            Insert(s);
        }
        Build();
        DFS(0);
        if (!ok) printf("NIE
    ");
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    day02-xml
    day01-java重点复习
    RPM包和YUM仓库管理
    Nginx的下载与安装
    yum源本地部署完后网络部署报错
    RAID和LVM
    磁盘管理
    xargs详解
    locate及find查找命令
    linux的进程和管道符(二)
  • 原文地址:https://www.cnblogs.com/mastervan/p/11312919.html
Copyright © 2011-2022 走看看