zoukankan      html  css  js  c++  java
  • BZOJ2938:[Poi2000]病毒

    BZOJ2938:[Poi2000]病毒

    考虑AC自动机匹配的过程

    如果下一个节点是危险节点,我们就不跳到这个节点

    如果下一个节点的 fail 是危险节点,我们也不跳到这个节点

    这个标记在 getfail 的时候就可以打上

    这样只要匹配的过程中能构成一个循环即可

    非常的妙啊

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    #include<queue>
    using namespace std;
    
    const int MAXN = 1000005;
    
    struct Node{
        int fail, nxt[2], lst;
        bool end;
        Node(){fail = lst = 0; memset(nxt, 0, sizeof(nxt));end = false;}
    }t[MAXN];
    int n, Root = 0, ptr = 0;
    char str[MAXN];
    bool getans = false, inque[MAXN], vis[MAXN];
    queue<int> q;
    
    inline int newnode() {
        return ++ptr;
    }
    inline void Insert(char *s) {
        int len = strlen(s), cur = Root;
        for(int i = 0; i < len; ++i) {
            register int x = s[i] - '0';
            if(!t[cur].nxt[x]) t[cur].nxt[x] = newnode();
            cur = t[cur].nxt[x];
        }
        t[cur].end = true;
        return;
    }
    inline void getfail() {
        t[Root].fail = 0;
        for(int i = 0; i < 2; ++i) 
            if(t[Root].nxt[i]) 
                q.push(t[Root].nxt[i]);
        while(!q.empty()) {
            int cur = q.front(); q.pop();
            for(int i = 0; i < 2; ++i) {
                register int son = t[cur].nxt[i], fail = t[cur].fail;
                if(!son) {
                    t[cur].nxt[i] = t[fail].nxt[i];
                    continue;
                }
                t[son].fail = t[fail].nxt[i];
                t[son].end |= t[t[son].fail].end;
                q.push(son);
            }
        }
        return;
    }
    void dfs(int cur) {
        if(getans) return;
        inque[cur] = true;
        for(int i = 0; i < 2; ++i) {
            int son = t[cur].nxt[i];
            if(inque[son]) {
                getans = true;
                break;
            }
            if(t[son].end || vis[son]) continue;
            vis[son] = true;
            dfs(son);
        }
        inque[cur] = false;
        return;
    }
    
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%s", str);
            Insert(str);
        }
        getfail();
        dfs(Root);
        if(getans) puts("TAK");
        else puts("NIE");
        return 0;
    }
    
    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    NLog简单配置与使用
    C#将类对象转换为字典
    .net中RSA加密解密
    .net引用System.Data.SQLite操作SQLite
    mongodb的安装以及客户端
    web api 二
    c语言中字符串的存储方式(转)
    cjson两种数组的解析方法(转)
    RT-Thread 自动初始化详解
    RTT与NRF52832移植问题记录
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9314803.html
Copyright © 2011-2022 走看看