洛谷P2444 病毒 [POI2000] AC自动机
正解:AC自动机
解题报告:
首先看到这种题目二话不说先把trie树和fail指针建立起来
然后就想鸭,如果我们想让模式串和文本串尽量不能匹配,就要想办法让它跳fail指针,而不是继续往下走,是趴
然后如果我可以一直跳fail指针始终没有到达文本串的结尾,就说明是可以构造一个无限长的字符串的对趴
于是就变成了,有一个图(trie树+fail指针指向的边就构成了一个图了嘛),如果能找到一个不包含文本串结尾节点的环就说明欧克,否则无法构造
就over辣!
昂还有个小技巧昂,就是在dfs找环的时候可以记录下去过什么点辣就可以不要重复去辣
#include<bits/stdc++.h> using namespace std; #define ll int #define rg register #define rp(i,x,y) for(rg ll i=x;i<=y;++i) const ll L=30000; ll n,cnt; bool vis[L+500],instck[L+500]; struct tre{ll to[2],fil;bool ed;tre(){to[0]=to[1]=0;ed=0;fil=0;}}tr[L+500]; inline ll read() { rg char ch=getchar();rg ll x=0;rg bool y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar(); if(ch=='-')ch=getchar(),y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar(); return y?x:-x; } inline void bd(string x) { ll lth=x.length()-1,nw=0; rp(i,0,lth){if(!tr[nw].to[x[i]^'0'])tr[nw].to[x[i]^'0']=++cnt;nw=tr[nw].to[x[i]^'0'];} tr[nw].ed=1; } inline void fl() { queue<ll> Q;rp(i,0,1)if(tr[0].to[i])Q.push(tr[0].to[i]); while(!Q.empty()) { ll nw=Q.front();Q.pop();tr[nw].ed|=tr[tr[nw].fil].ed; rp(i,0,1){if(tr[nw].to[i])tr[tr[nw].to[i]].fil=tr[tr[nw].fil].to[i],Q.push(tr[nw].to[i]);else tr[nw].to[i]=tr[tr[nw].fil].to[i];} } } inline void dfs(ll x) { if(tr[x].ed)return; if(instck[x]){printf("TAK");exit(0);} if(vis[x])return;instck[x]=vis[x]=1; rp(i,0,1)if(tr[x].to[i])dfs(tr[x].to[i]); instck[x]=0; } int main() { n=read();rp(i,1,n){string x;cin>>x;bd(x);}fl();dfs(0);printf("NIE\n"); return 0; }