• [POI 2000] 病毒


    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=2938

    [算法]

            首先建出给定字符串集的AC自动机

            存在无限长的代码当且仅当 : AC自动机上存在一个环且环上没有危险节点

            时间复杂度 : O(N)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXP 300010
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    int n;
    char s[MAXP];
    
    struct AC_Automation
    {
        int sz , rt , timer;
        int fail[MAXP];
        bool danger[MAXP] , vis[MAXP] , ins[MAXP];
        int child[MAXP][2];
        inline void init()
        {
            timer = 0;
            sz = 0;
            rt = newnode();
        }
        inline void chkmin(int &x , int y)
        {
            x = min(x , y);
        }
        inline int newnode()
        {
            ++sz;
            child[sz][0] = child[sz][1] = -1;
            fail[sz] = danger[sz] = 0;
            return sz;
        }
        inline void insert(char *s)
        {
            int now = rt;
            for (int i = 1; i <= strlen(s + 1); i++)
            {
                int nxt = s[i] - '0';
                if (child[now][nxt] == -1) child[now][nxt] = newnode();
                now = child[now][nxt];
            }
            danger[now] = 1;
        }
        inline void rebuild()
        {
            queue< int > q;
            fail[rt] = rt;
            for (int i = 0; i < 2; i++)
            {
                if (child[rt][i] == -1)
                    child[rt][i] = rt;
                else
                {
                    fail[child[rt][i]] = rt;
                    q.push(child[rt][i]);
                }
            }
            while (!q.empty())
            {
                int cur = q.front();
                q.pop();
                for (int i = 0; i < 2; i++)
                {
                    if (child[cur][i] == -1)
                        child[cur][i] = child[fail[cur]][i];
                    else
                    {
                        fail[child[cur][i]] = child[fail[cur]][i];
                        danger[child[cur][i]] |= danger[fail[child[cur][i]]];
                        q.push(child[cur][i]);
                    }
                }
            }
        }
        inline void solve(int now)
        {
            if (ins[now])
            {
                printf("TAK
    ");
                exit(0);
            }
            if (vis[now] || danger[now]) return;
            vis[now] = ins[now] = 1;
            if (child[now][0] != -1) solve(child[now][0]);
            if (child[now][1] != -1) solve(child[now][1]);
            ins[now] = 0;
        } 
    } ACAM;
    
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
    template <typename T> inline void read(T &x)
    {
       T f = 1; x = 0;
       char c = getchar();
       for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
       for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
       x *= f;
    }
    
    int main()
    {
        
        scanf("%d" , &n);
        ACAM.init();
        for (int i = 1; i <= n; i++)
        {
            scanf("%s" , s + 1);
            ACAM.insert(s); 
        }
        ACAM.rebuild();
        ACAM.solve(1);
        printf("NIE
    ");
        
        return 0;
    }
  • 相关阅读:
    [Linux] Chmod 改变权限
    [linux命令]基本命令
    [Linux命令] 查看目录大小du
    [Linux命令]格式化mkfs
    在VMWare下的Linux切换
    .net的MSMQ异步调用
    CASSINI源代码分析
    [Wix] RadioButton与ListItem的属性要改掉了
    如何快速生成Insert数据插入语句?
    撕纸
  • 原文地址:https://www.cnblogs.com/evenbao/p/10355681.html
Copyright © 2020-2023  润新知