zoukankan      html  css  js  c++  java
  • 【[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;
    }
    
  • 相关阅读:
    SQLAlchemy教程-第二章-SQL常用查询的ORM写法
    弹性数组
    C++模板
    typedef 函数名
    typedef 函数指针
    备忘录:“#ifdef __cplusplus extern "C" { #endif”的定义
    linux mmap 内存映射
    生成模型与判别模型(转)
    DL反向传播理解
    UFLDL(Unsupervised Feature Learning and Deep Learning)
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207921.html
Copyright © 2011-2022 走看看