• [POI2000] 病毒


    题目链接(这次是落咕的):戳我
    做这个题目之前可以考虑先去把落咕上的两个AC自动机的模板写了——这个 (;)还有这个

    AC自动机是什么呢?是一种多模匹配的算法。有可能很多人都说它是KMP+Trie。

    一般的AC自动机解决的是字符串匹配一类的问题,但是这道题绕了个弯,让求有没有可能存在一个无限长的串,使得其中不包含给定的一些文本串——也就是说存不存在一个串,无法匹配给定的这些串。

    那么也就是说,要尽可能地让模式串失配。有fail指针就要往上面跳。我们在预先处理fail指针的时候就把最后节点的儿子指向了自己fail指针所指的节点的相同的儿子。之后在建出来的trie树上跑dfs,如果处理当前匹配可以跳到一个环里,那么自然可以构成一个无限长的字符串满足题意。反之,则每次往下一层必定有匹配,最终一定会匹配上病毒代码。

    所以就是AC自动机+dfs!需要注意的一点是,我们要给病毒串的末尾打标记,然后它的子节点必须也要继承上这个标记(因为如果匹配到这个子节点,那么一定匹配了它的父亲,匹配到它的父亲的时候就已经是匹配上病毒串了)。dfs的时候如果遇到标记直接return,因为这样就匹配上了病毒串,而我们要找的是无法完成匹配的串。还有一点,就是如果遇到非当前次经过的节点(对应代码为pre[now]==1),也要直接return。因为如果遇到了它,那么意味着这之前这个节点并没有成功跳进环,所以进入到这个节点是没用的。

    最后注意既然我们是要找当前无法完成匹配(也就是跳进环)的一些节点,那么我们处理完一定要把回溯。。。。。

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define MAXN 100010
    using namespace std;
    struct tree{int fail,end,vis[26];}ac[MAXN*10];
    int cnt=0,n,t;
    int head[MAXN],done[MAXN],pre[MAXN];
    string s[2010];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline void add(int from,int to){edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;}
    inline void build(string s)
    {
        int len=s.length();
        int now=0;
        for(int i=0;i<len;i++)
        {
            if(ac[now].vis[s[i]-'0']==0)
            {
                ac[now].vis[s[i]-'0']=++cnt;
                add(now,ac[now].vis[s[i]-'0']);
            }
            now=ac[now].vis[s[i]-'0'];
        }
        ac[now].end=1;
    }
    inline void get_fail()
    {
        queue<int>q;
        for(int i=0;i<=1;i++)
            if(ac[0].vis[i])
                ac[ac[0].vis[i]].fail=0,q.push(ac[0].vis[i]);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=0;i<=1;i++)
            {
                if(ac[u].vis[i]!=0)
                {
                    ac[ac[u].vis[i]].fail=ac[ac[u].fail].vis[i];
                    q.push(ac[u].vis[i]);
                    if(ac[ac[u].fail].end==1) ac[u].end=1;
                }
                else ac[u].vis[i]=ac[ac[u].fail].vis[i];
            }
        }
    }
    inline void dfs(int now)
    {
        if(ac[now].end) return;
        if(done[now]){printf("TAK
    ");exit(0);}
        if(pre[now]) return;
        pre[now]=done[now]=1;
        for(int i=0;i<=1;i++)
            if(ac[now].vis[i])
                dfs(ac[now].vis[i]);
        done[now]=0;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++) cin>>s[i],build(s[i]);
        get_fail();
        dfs(0);
        printf("NIE
    ");
        return 0;
    }
    
  • 相关阅读:
    mysql简单介绍及安装
    LVS
    LAMP架构
    记录一个低级又让人踩坑的bug(org.springframework.web.method.annotation.MethodArgumentTypeMismatchException)
    Hadoop通过idea连接远程集群出现的用户权限问题
    linxu离线环境安装docker
    linux中oracle的使用问题简单罗列与解决
    Linux下安装Oracle详细版-附oracle11g软件包
    Host is not allowed to connect to this MySQL server问题解决
    kettle的安装使用及介绍
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10301223.html
Copyright © 2020-2023  润新知