2015湖南省队集训DAY6——B题(BZOJ4179)

题面挺扯的,我就直接说人话算了。
题目大意:给你若干个病毒串,问你能不能构造出长度大于n的字符串使其中不出现任何一个字符串。
多组数据,总文件大小小于1M
题解:
联动:BZOJ2938
基本是原题,稍作了改动。
考虑ac自动机。
所求即为ac自动机中是否存在长度大于等于l的路径
先将所有的串插进去,然后构造失配指针。
显然的,插入后的末端节点肯定是不能经过的。
但仅这样显然是不可以的,我们考虑在匹配时,如果失配指针指向的节点是danger节点,那么这个节点也是不能经过的(显然)。
所以考虑ac自动机还剩下的节点,如果这张图中有环,那么一定存在长度大于等于l的路径(显然)。如果没有,剩下的就是个DAG,DAG上的最长路就是一傻逼问题。

代码丑,见谅

#include 

using namespace std;

typedef long long ll;
typedef double db;

const int inf=0x3f3f3f3f;

int getint()
{
    int f=1,g=0;char c=getchar();
    while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0' && c<='9')g=(g<<3)+(g<<1)+c-'0',c=getchar();
    return f*g;
}

const int maxsize=1000005;
const int maxk=2;

int s,l;

namespace Aho_Corasick_Automaton{

    int next[maxsize][maxk];
    bool flag[maxsize];
    int fail[maxsize];
    int root;
    int tot;

    void init()
    {
        memset(next,-1,sizeof next);
        memset(flag,false,sizeof flag);
        memset(fail,0,sizeof fail);
        tot=0;
    }

    char st[maxsize];

    void insert()
    {   
        int now=root;
        int len=strlen(st+1);
        for(int i=1;i<=len;i++)
        {
            if(next[now][st[i]=='T']==-1)
            {
                next[now][st[i]=='T']=++tot;                
            }
            now=next[now][st[i]=='T'];
        }
        flag[now]=true;
    }

    void build()
    {
        queue<int> q;
        fail[root]=root;

        for(int i=0;i<2;i++)
        {
            if(next[root][i]==-1)
            {
                next[root][i]=root;
            }
            else
            {
                fail[next[root][i]]=root;
                q.push(next[root][i]);
            }           
        }
        while(!q.empty())
        {
            int now=q.front();q.pop();
            flag[now]|=flag[fail[now]];
            for(int i=0;iif(next[now][i]==-1)
                {
                    next[now][i]=next[fail[now]][i];
                }
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    q.push(next[now][i]);
                }
            }
        }
        /*
        for(int i=1;i<=tot;i++)
        {
            if(flag[fail[i]])
            {
                flag[i]=true;
            }
        }*/     
    }

    bool vis[maxsize];
    int f[maxsize];
    bool find;

    void dfs(int x,int len)
    {
        if(find)return;
        if(flag[x])return;
        if(len>=l)
        {
            find=true;
            return;
        }
        if(vis[x])
        {
            find=true;
            return;
        }
        vis[x]=true;
        for(int i=0;i1);
        }
        vis[x]=false;       
    }

    void solve()
    {
        init();
        memset(vis,false,sizeof vis);
        find=false;
        for(int i=1;i<=s;i++)
        {
            scanf("%s",st+1);
            insert();
        }
        //puts("readin ok");
        build();
        //puts("build ok");
        memset(f,-1,sizeof f);
        dfs(root,0);
        if(find)puts("Yes");
        else puts("No");
    }
};


int main()
{
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);

    while(scanf("%d %d",&s,&l)!=EOF)
    {
        Aho_Corasick_Automaton::solve();
    }

    return 0;
}

orz今天ak的zyf大爷

你可能感兴趣的:(字符串,水题,ac自动机)