标签:选择 code bit 无线 节点 def trie 判断 front
给定一些字符串,问是否存在一个无限长度的字符串,使得它不包含任何一个给定的串
将所有串加入AC自动机,那么我们从根节点选择的一个无线字符串显然不能经过任何一个带有end标记的节点,不然就说明其中包含了这个节点对应的字符串。
于是用fail标记建成trie图,判断trie图上面有没有一个不经过end标记的环即可
Code:
#include<bits/stdc++.h>
#define N 30005
using namespace std;
int n;
int nxt[N][2],fail[N],ndsum;
char c[N];
bool is_end[N],vis[N],st[N];
void ad(char a[])
{
int l=strlen(a),now=0;
for(int i=0;i<l;++i)
{
int pp=a[i]-'0';
if(!nxt[now][pp]) nxt[now][pp]=++ndsum;
now=nxt[now][pp];
}
is_end[now]=1;
}
void getfail()
{
queue<int> q;
for(int i=0;i<2;++i) if(nxt[0][i]) q.push(nxt[0][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<2;++i)
if(nxt[u][i]) fail[nxt[u][i]]=nxt[fail[u]][i],q.push(nxt[u][i]),is_end[nxt[u][i]]|=is_end[fail[nxt[u][i]]];
else nxt[u][i]=nxt[fail[u]][i];
}
}
bool dfs(int u)
{
if(st[u]) return true;
if(vis[u]) return false;
vis[u]=st[u]=1;
for(int i=0;i<2;++i)
{
if(nxt[u][i]&&!is_end[nxt[u][i]]) if(dfs(nxt[u][i])) return true;
}
st[u]=0;
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%s",c);
ad(c);
}
getfail();
memset(vis,0,sizeof(vis));
if(dfs(0)) printf("TAK\n");
else printf("NIE\n");
return 0;
}
标签:选择 code bit 无线 节点 def trie 判断 front
原文地址:https://www.cnblogs.com/Chtholly/p/11185755.html