题面挺扯的,我就直接说人话算了。
题目大意:给你若干个病毒串,问你能不能构造出长度大于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