BZOJ2938: [Poi2000]病毒
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2938: [Poi2000]病毒相关的知识,希望对你有一定的参考价值。
AC自动机上的各种处理一直让我很迷。一个主要懵逼的点是不清楚对于不存在的字母所对应的方案如何处理。做了两道题大概比较清楚了。
其实对于不存在的字母节点不需要特殊的处理。因为如果累加方案的话,其方案会自动累加到$root$节点。而其fail指针也会自动指向自己。
另外这道题的判环参考了黄学长的代码,类似于一个简化版的tarjan。
//BZOJ 2938 //by Cydiater //2016.10.18 #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <string> #include <cstring> #include <iomanip> #include <queue> #include <map> #include <ctime> #include <algorithm> using namespace std; #define ll long long #define up(i,j,n) for(int i=j;i<=n;i++) #define down(i,j,n) for(int i=j;i>=n;i--) const int MAXN=1e6+5; const int oo=0x3f3f3f3f; inline int read(){ char ch=getchar();int x=0,f=1; while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int N,len,next[MAXN][2],fail[MAXN],cnt=0,head,tail,q[MAXN]; bool end[MAXN],vis[MAXN],ins[MAXN]; char s[MAXN]; namespace solution{ void insert(){ int now=0; up(i,1,len){ int num=s[i]-‘0‘; if(!next[now][num])next[now][num]=++cnt; now=next[now][num]; } end[now]=1; } void init(){ N=read(); memset(end,0,sizeof(end)); up(i,1,N){ scanf("%s",s+1); len=strlen(s+1); insert(); } } void buildAC(){ head=1;tail=0; up(i,0,1)if(next[0][i])q[++tail]=next[0][i]; for(;head<=tail;head++){ int now=q[head];end[now]|=end[fail[now]]; up(i,0,1){ int son=next[now][i]; if(son>0){ fail[son]=next[fail[now]][i]; q[++tail]=son; } else next[now][i]=next[fail[now]][i]; } } } bool dfs(int node){ ins[node]=1; up(i,0,1){ int son=next[node][i]; if(ins[son])return 1; if(vis[son]||end[son])continue; vis[son]=1; if(dfs(son))return 1; } ins[node]=0; return 0; } void slove(){ buildAC(); memset(vis,0,sizeof(vis)); if(dfs(0))puts("TAK"); else puts("NIE"); } } int main(){ using namespace solution; init(); slove(); return 0; }
以上是关于BZOJ2938: [Poi2000]病毒的主要内容,如果未能解决你的问题,请参考以下文章