传送门:https://www.luogu.org/problem/P2444
这种题一眼AC自动机(
但是AC自动机有些点要格外注意,比如:我这个傻缺就把ch[][]和fail[] 开成了char类型 QWQ
来看这道题在一个无限长的串中不让出现模式串。既然无限长那么我们就需要在trie图中找到一个合法的环不断循环下去
那么我们的任务就成了在trie图中找环(TIP—当一个点的fail指针指向的点为一个模式串的结尾,那么这个点也是不合法的)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define R register using namespace std; int n,cnt,vis[40000],ch[40000][2],fail[40000]; char s[30010]; void make() { int u=0,len=strlen(s); for(R int i=0;i<len;i++){ int c=s[i]-'0'; if(!ch[u][c]) ch[u][c]=++cnt; u=ch[u][c]; } vis[u]=-1; } void AC(){ queue<int> q; for(R int i=0;i<=1;i++){ if(ch[0][i]){ q.push(ch[0][i]); fail[ch[0][i]]=0; } } while(q.size()){ int u=q.front();q.pop(); for(R int i=0;i<=1;i++){ if(!ch[u][i]) ch[u][i]=ch[fail[u]][i]; else{ int v=fail[u]; while(v&&!ch[v][i]) v=fail[v]; fail[ch[u][i]]=ch[v][i]; q.push(ch[u][i]); if(vis[ch[fail[u]][i]]==-1) vis[ch[u][i]]=-1; } } } } bool dfs(int u){ vis[u]=1; for(R int i=0;i<=1;i++){ if(vis[ch[u][i]]==1) return true; if(vis[ch[u][i]]==2||vis[ch[u][i]]==-1) continue; if(dfs(ch[u][i])) return true; } vis[u]=2; return false; } int main (){ scanf("%d",&n); for(R int i=1;i<=n;i++){ scanf("%s",s); make(); } AC(); if(dfs(0)) puts("TAK"); else puts("NIE"); return 0; }