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

题面挺扯的,我就直接说人话算了。

题目大意:给你若干个病毒串,问你能不能构造出长度大于n的字符串使其中不出现任何一个字符串。

多组数据,总文件大小小于1M

题解:

联动:BZOJ2938

基本是原题,稍作了改动。

考虑ac自动机。

所求即为ac自动机中是否存在长度大于等于l的路径

先将所有的串插进去,然后构造失配指针。

显然的,插入后的末端节点肯定是不能经过的。

但仅这样显然是不可以的,我们考虑在匹配时,如果失配指针指向的节点是danger节点,那么这个节点也是不能经过的(显然)。

所以考虑ac自动机还剩下的节点,如果这张图中有环,那么一定存在长度大于等于l的路径(显然)。如果没有,剩下的就是个DAG,DAG上的最长路就是一傻逼问题。

代码丑,见谅

#include <bits/stdc++.h>

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;i<maxk;i++)
            {
                if(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;i<maxk;i++)
        {
            dfs(next[x][i],len+1);
        }
        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大爷

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-24 22:51:59

2015湖南省队集训DAY6——B题(BZOJ4179)的相关文章

2015湖南省队集训DAY3——Light

Light [问题描述] "若是万一琪露诺(俗称 rhl)进行攻击,什么都好,冷静地回答她的问题来吸引 对方表现出兴趣的话,那就慢慢地反问.在她考虑答案的时候,趁机逃吧.就算是很简 问题,她一定也答不上来." --<上古之魔书> 天空中出现了许多的北极光,这些北极光组成了一个长度为n的正整数数列 a[i],远 魔书上记载到:2 个位置的 graze 值为两者位置差与数值差的和: graze(x,y)=|x-y|+|a[x]-a[y]|. 要想破解天罚,就必须支持 2种操作(

湖南省队集训 -- 1

不知道为什么今天状态 大 好 可能是暴力分比较简单吧,来认真写一下总结 开局睡了1h-- 然后考虑a题,发现特殊性:因为最后的和一定是10^n的,最后两个数一定是后面一段全是0,前面一段两个数的和是⑨,0和⑨中间夹一对和为10 然后脑补正解不能,暴力枚举一下好像可以,就是判断是在不好写 然后考虑b题,看N^2算法,脑玩了一下发现距离是不会变得,如果钦定了一个点建站第1~n-1个点产生的权值是不会变得,最后一个点的距离也变不了,唯一得变量需求要乘距离,然后把剩下的不变量加起来,这就是个kx+b的形

省队集训day6 B

一道AC自动机题···· 一定要把一个节点没有的儿子接到它fai的儿子,否则会卡到n^2的······· 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<ctime> 6 #define maxn 1048580 7 #define maxl 10005 8 using namespace std; 9 typ

[2018湖南省队集训] 6.24 T1 marshland

题面在这里! 一开始感觉像一个类似二分图的最小割,于是成功跑偏2333333 很容易发现一个关键性质,'L'的两个角落在的偶数格 的行(或者列)的奇偶性一定不同.... 于是我们再把偶数格按照行(或者列)的奇偶性再细分成 两类,可以发现只有一个奇数格向旁边的两类偶数格都有空挡的话,才能放下一个L. 所以我们把放L看成网络中的一条流量,要经过三种点,于是对于奇数格拆点限流然后四列点直接跑最大费用最大流就行了.... 因为不用把m个L都放完,所以增广到 dis<0 的时候跳出就好啦.... #inc

省队集训day6 A

code: 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 262146 7 #define mod 950009857 8 #define g 7 9 using namespace std; 10 typedef long long int64; 11 char

省队集训 Day6 序列

[题目大意] 给出$n$个数的序列$a_1, a_2, ..., a_n$,有$m$次操作,为下面三种: $A~l~r~d$:区间$[l,r]$,全部加$d$. $M~l~r~d$:区间$[l,r]$,对$d$取max. $Q~x$:询问$a_x$的值. 对于30%的数据,$n, m\leq 10^4$: 对于60%的数据,保证数据随机: 对于100%的数据,满足$n, m \leq 10^5$,所有数的绝对值不超过$2^{31} - 1$.保证也是随机的. [题解] 显然正解是吉司机线段树,我

省队集训day6 C

Description 给定平面上的 N 个点, 其中有一些是红的, 其他是蓝的.现在让你找两条平行的直线, 使得在保证    不存在一个蓝色的点 被夹在两条平行线之间,不经过任何一个点, 不管是蓝色点还是红色点的前提下, 被夹在平行线之间的红色点个数最多 Input 第1行: 一个整数 N (1 <= N <= 1000)    第2..N+1行: 每行是一个点的坐标以及它的颜色.                坐标用2个 绝对值<10^9 的整数表示                颜

2015湖南省选集训DAY5——work(BZOJ4177)

Description Mike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不同,其中第i个牲畜围栏中的动物长大后,每只牛可以卖a[i]元,每只羊可以卖b[i]元,为了防止牛羊之间相互影响,Mike找到了m条规律,每条规律给出一个三元组(i, j, k)表示如果第i个围栏和第j个围栏养的是不同的动物,那么Mike就需要花费k的代价请人帮忙处理牛羊之间的影响.不过同时Mike也发现k条特殊的规则(S, a, b),表示如

CSU OJ 1112机器人的指令 (湖南省12年省赛题)

 Welcome to CSU Online Judge! 1112: 机器人的指令 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 274  Solved: 97 [Submit][Status][Web Board] Description 数轴原点有一个机器人.该机器人将执行一系列指令,你的任务是预测所有指令执行完毕之后它的位置. ·LEFT:往左移动一个单位 ·RIGHT: 往右移动一个单位 ·SAME AS i: 和第i 条执行相同的