码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2938

时间:2017-07-26 23:29:51      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:pen   struct   splay   自动机   name   gif   false   code   display   

AC自动机+trie图优化

很明显就是要一个串不能匹配到任何一个病毒,那么我们就建一个AC自动机

不能匹配的话也就是一个节点不能是单词结束节点,fail指针也不能是结束节点

然后就卡壳了。。。zz

我们把自动机建成trie图,也就是不存在的节点直接指向原来fail指针,然后我们只要在这个图上找有没有环就可以了。

因为ac自动机当不能继续匹配,也就是没有儿子节点,就会沿着fail指针走,否则就沿着儿子走,于是我们就把不存在的儿子指向fail,是一种优化,如果有一个无限长的串,也就是这个串能不停地匹配,不会走到危险节点,那么肯定就有环了,因为自动机是有限的。

技术分享
#include<bits/stdc++.h>
using namespace std;
const int N = 30010;
int n;
char s[N];
struct acautomation {
    int root, cnt;  
    int child[N][2], fail[N], danger[N], vis[N], inq[N];
    void insert(char s[])
    {
        int now = root;
        for(int i = 0; i < strlen(s); ++i)
        {
            int x = s[i] - 0;
            if(!child[now][x]) child[now][x] = ++cnt;
            now = child[now][x];
        }
        danger[now] = 1;
    }
    void build_fail()
    {
        queue<int> q;
        for(int i = 0; i < 2; ++i) if(child[root][i])
        {
            q.push(child[root][i]);
            fail[child[root][i]] = 0;
        }
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int i = 0; i < 2; ++i) 
            {
                int v = child[u][i];
                if(!v) child[u][i] = child[fail[u]][i];
                else
                {
                    int now = fail[u];
                    while(now != root && !child[now][i]) now = fail[now];
                    fail[v] = child[now][i];
                    danger[v] |= danger[fail[v]];
                    q.push(v);
                }
            }
        }
    }
    bool dfs(int u)
    {
        inq[u] = 1;
        for(int i = 0; i < 2; ++i)
        {
            int v = child[u][i];
            if(inq[v]) return true;
            if(danger[v] || vis[v]) continue;
            vis[v] = 1;
            if(dfs(v)) return true; 
        }
        inq[u] = 0;
        return false;
    }
} ac;
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%s", s);
        ac.insert(s);
    }
    ac.build_fail();
    if(ac.dfs(0)) puts("TAK");
    else puts("NIE");
    return 0;
}
View Code

 

bzoj2938

标签:pen   struct   splay   自动机   name   gif   false   code   display   

原文地址:http://www.cnblogs.com/19992147orz/p/7242285.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!