https://www.luogu.org/problemnew/show/P2444
有点恶心,不太明白fail的意义。
#include<bits/stdc++.h> using namespace std; #define ll long long struct Trie{ int nex[60010][2],fail[60010],End[60010]; int root,L; int newnode(){ /*for(int i=0;i<26;i++) nex[L][i]=-1;*/ End[L++]=0; return L-1; } int cnt; void init(){ L=0; cnt=0; memset(nex,-1,sizeof(nex)); root=newnode(); } void insert(char buf[]){ int len=strlen(buf); int now=root; for(int i=0;i<len;i++){ int &t=nex[now][buf[i]-'0']; if(t==-1) t=newnode(); now=t; } End[now]++; cnt++; } void build(){ queue<int>Q; fail[root]=root; for(int i=0;i<2;i++){ if(nex[root][i]==-1){ nex[root][i]=root; //根节点没有对应的分支,还是必须回到根节点开始匹配 } else{ //根节点的后继失配,先假定回到根节点匹配 fail[nex[root][i]]=root; Q.push(nex[root][i]); } } while(!Q.empty()){ int now=Q.front(); Q.pop(); for(int i=0;i<2;i++) if(nex[now][i]==-1){ //某个节点没有这个对应的分支,它失配了,沿着失配边去到最近的有这个分支的边? nex[now][i]=nex[fail[now]][i]; } else{ fail[nex[now][i]]=nex[fail[now]][i]; Q.push(nex[now][i]); //如果这个节点的fail指针指向的点是End,那么因为这个节点蕴含他的fail节点,所以他也是End End[now]|=End[fail[now]]; } } } /*int query(char buf[]){ int len=strlen(buf); int now=root; int res=0; for(int i=0;i<len;i++){ now=nex[now][buf[i]-'0']; int temp=now; while(temp!=root&&End[temp]!=-1){ res+=End[temp]; End[temp]=-1; temp=fail[temp]; } //if(res==cnt) //return res; } return res; }*/ int vis[60005]; int instack[60005]; int find_circle(){ memset(vis,0,sizeof(vis)); memset(vis,0,sizeof(instack)); return dfs(root); } int dfs(int id){ instack[id]=1; vis[id]=1; for(int i=0;i<2;i++){ if(instack[nex[id][i]]){ //该节点的下一条边在dfs栈中,是反向边 printf("TAK "); exit(0); } if(vis[nex[id][i]]==0){ //不访问已经到过的表亲,表亲不可能成环 if(End[nex[id][i]]==0){ //下一个点不是病毒 dfs(nex[id][i]); } } } instack[id]=0; return 0; } }; char buf[100010]; Trie ac; int n; void solve(){ while(~scanf("%d",&n)){ if(n==0) break; ac.init(); for(int i=0;i<n;i++){ scanf("%s",buf); ac.insert(buf); } ac.build(); //scanf("%s",buf); if(ac.find_circle()==0){ cout<<"NIE"<<endl; } } } int main(){ #ifdef Yinku freopen("Yinku.in","r",stdin); //freopen("Yinku.out","w",stdout); #endif // Yinku solve(); }