题目:https://www.luogu.org/problemnew/show/P2444
AC自动机上 dfs,不走结尾点,如果走出环就是有无限长度的串;
RE无数,原来是数组开成 2000 的了...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; int const xn=2005,xm=30005; int n,cnt,c[xm][2],fail[xm]; bool vis[xm],end[xm],in[xm]; char dc[xm]; queue<int>q; void build() { int nw=0,l=strlen(dc); for(int i=0;i<l;i++) { int t=dc[i]-'0'; if(!c[nw][t])c[nw][t]=++cnt; nw=c[nw][t]; } end[nw]=1; } void getfail() { for(int i=0;i<=1;i++) if(c[0][i])fail[c[0][i]]=0,q.push(c[0][i]); while(q.size()) { int x=q.front(); q.pop(); end[x]|=end[fail[x]]; for(int i=0;i<=1;i++) { if(c[x][i])fail[c[x][i]]=c[fail[x]][i],q.push(c[x][i]); else c[x][i]=c[fail[x]][i]; } } } bool dfs(int x) { vis[x]=1; in[x]=1; for(int i=0;i<=1;i++) { if(!c[x][i]||end[c[x][i]])continue;//也可没有 !c[x][i] if(in[c[x][i]])return 1;//注意在判断 vis 之前 if(vis[c[x][i]])continue;//!return 0! vis[c[x][i]]=1; if(dfs(c[x][i]))return 1;// } in[x]=0; return 0; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%s",dc),build(); getfail(); if(dfs(0))printf("TAK "); else printf("NIE "); return 0; }