【題解】P2444 病毒
阿新 • • 發佈:2019-02-07
show uil href pac 給定 就是 dfs using cpp
【題解】[P2444 POI2000]病毒
一道\(ac\)自動機好題...
考慮危險的字符串是什麽意思,就是在這個文本串中有模式串的匹配,這樣的匹配可以通過\(ac\)自動機完成。
那麽給定一個字符串如何判斷是否有病毒,直接就是看ac自動機是否匹配成功。
考慮“無限長的安全字符串”代表什麽意思,就是在\(ac\)自動機找到一個環。可以用閹割版的\(tarjin\)
#include<bits/stdc++.h> using namespace std; #define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t) #define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t) #define ERP(t,a) for(register int t=head[a];t;t=e[t].nx) #define Max(a,b) ((a)<(b)?(b):(a)) #define Min(a,b) ((a)<(b)?(a):(b)) #define midd register int mid=(l+r)>>1 #define TMP template < class ccf > TMP inline ccf qr(ccf b){ char c=getchar(); int q=1; ccf x=0; while(c<48||c>57) q=c==45?-1:q,c=getchar(); while(c>=48&&c<=57) x=x*10+c-48,c=getchar(); return q==-1?-x:x; } const int maxac=30005; int n; string x; struct AC{ int son[2]; int fail;int cnt; inline int& operator [](int o){ return son[o&1]; } inline int& operator [](char o){ return son[(o-‘0‘)&1]; } }ac[maxac]; int act; inline void build(int lit){ int now=0; RP(t,0,lit-1){ if(!ac[now][x[t]]) ac[now][x[t]]=++act; now=ac[now][x[t]]; } ac[now].cnt++; //cout<<"build="<<now<<endl; } queue< int > q; inline void gen(){ RP(t,0,1) if(ac[0][t]) q.push(ac[0][t]); while(!q.empty()){ int now=q.front(); q.pop(); RP(t,0,1){ if(ac[now][t]){ ac[ac[now][t]].fail=ac[ac[now].fail][t]; ac[ac[now][t]].cnt|=ac[ac[ac[now].fail][t]].cnt; q.push(ac[now][t]); } else ac[now][t]=ac[ac[now].fail][t]; } } } bool in[maxac]; bool usd[maxac]; void dfs(int now){ usd[now]=in[now]=1; RP(t,0,1){ if(in[ac[now][t]]) puts("TAK"),exit(0); if(!ac[ac[now][t]].cnt) dfs(ac[now][t]); } in[now]=0; } int main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif n=qr(1); RP(t,1,n){ cin>>x; build(x.length()); } gen(); if(!ac[0].cnt) dfs(0); puts("NIE"); return 0; }
【題解】P2444 病毒