首页 > 代码库 > BZOJ2938: [Poi2000]病毒
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]病毒
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。