【[POI2000]病毒】

\(Ac\)自动机好题了

这个题要求我们一直无法匹配到结束标记,所以我们直接在\(trie\)图上找到一个环,这个环可以被根节点到达,之后还没有结束标记

发现自己不会\(dfs\)找环,于是直接莽上\(tarjan\)

之后一直写挂各种\(sb\)

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define re register
#define LL long long
#define maxn 30005
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
struct E{int v,nxt;}e[maxn<<4];
int head[maxn];
int n,m,cnt,top,tot,p,num,mid;
char S[maxn];
int son[maxn][2],fail[maxn],flag[maxn];
int dfn[maxn],low[maxn],f[maxn],st[maxn],col[maxn],d[maxn],vis[maxn];
inline void ins()
{
	scanf("%s",S+1);
	int len=strlen(S+1),now=0;
	for(re int i=1;i<=len;i++)
	{if(!son[now][S[i]-'0']) son[now][S[i]-'0']=++cnt;now=son[now][S[i]-'0'];}
	flag[now]=1;
}
inline void Build()
{
	std::queue<int> q;
	for(re int i=0;i<2;i++) if(son[0][i]) q.push(son[0][i]);
	while(!q.empty())
	{
		int k=q.front();q.pop();
		flag[k]|=flag[fail[k]];
		for(re int i=0;i<2;i++)
		if(son[k][i]) fail[son[k][i]]=son[fail[k]][i],q.push(son[k][i]);
			else son[k][i]=son[fail[k]][i];
	}
}
void tarjan(int x)
{
	if(flag[x]) return;
	f[x]=1,st[++top]=x,dfn[x]=low[x]=++tot;
	for(re int i=0;i<2;i++)
	{
		if(flag[son[x][i]]) continue;
		if(!dfn[son[x][i]]) tarjan(son[x][i]),low[x]=min(low[x],low[son[x][i]]);
		else if(f[son[x][i]]) low[x]=min(low[x],dfn[son[x][i]]);
	}
	if(dfn[x]==low[x])
	{
		++p;int t=0;
		do {mid=st[top--];f[mid]=0,t++,col[mid]=p;}while(x!=mid);
		d[p]=t;
	}
}
inline void add_edge(int x,int y){e[++num].v=y,e[num].nxt=head[x],head[x]=num;}
int dfs(int x)
{
	if(d[x]>1) return 1;
	int ff=0;
	vis[x]=1;
	for(re int i=head[x];i;i=e[i].nxt)
	if(!vis[e[i].v]) ff|=dfs(e[i].v);
	return ff;
}
int main()
{
	scanf("%d",&n);
	for(re int i=1;i<=n;i++) ins();Build();
	for(re int i=0;i<=cnt;i++) if(!dfn[i]) tarjan(i);
	for(re int i=0;i<=cnt;i++)
		for(re int j=0;j<2;j++) if(col[son[i][j]]!=col[i]) add_edge(col[i],col[son[i][j]]);
	for(re int i=0;i<=cnt;i++)
		for(re int j=0;j<2;j++)
			if(son[i][j]==i) d[col[i]]++;
	vis[0]=1;
	if(dfs(col[0])) puts("TAK");else puts("NIE");
	return 0;
}
posted @ 2019-01-02 12:22  asuldb  阅读(117)  评论(0编辑  收藏  举报