BZOJ2938:[Poi2000]病毒
考虑AC自动机匹配的过程
如果下一个节点是危险节点,我们就不跳到这个节点
如果下一个节点的 fail 是危险节点,我们也不跳到这个节点
这个标记在 getfail 的时候就可以打上
这样只要匹配的过程中能构成一个循环即可
非常的妙啊
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cctype> #include<cstdio> #include<queue> using namespace std; const int MAXN = 1000005; struct Node{ int fail, nxt[2], lst; bool end; Node(){fail = lst = 0; memset(nxt, 0, sizeof(nxt));end = false;} }t[MAXN]; int n, Root = 0, ptr = 0; char str[MAXN]; bool getans = false, inque[MAXN], vis[MAXN]; queue<int> q; inline int newnode() { return ++ptr; } inline void Insert(char *s) { int len = strlen(s), cur = Root; for(int i = 0; i < len; ++i) { register int x = s[i] - '0'; if(!t[cur].nxt[x]) t[cur].nxt[x] = newnode(); cur = t[cur].nxt[x]; } t[cur].end = true; return; } inline void getfail() { t[Root].fail = 0; for(int i = 0; i < 2; ++i) if(t[Root].nxt[i]) q.push(t[Root].nxt[i]); while(!q.empty()) { int cur = q.front(); q.pop(); for(int i = 0; i < 2; ++i) { register int son = t[cur].nxt[i], fail = t[cur].fail; if(!son) { t[cur].nxt[i] = t[fail].nxt[i]; continue; } t[son].fail = t[fail].nxt[i]; t[son].end |= t[t[son].fail].end; q.push(son); } } return; } void dfs(int cur) { if(getans) return; inque[cur] = true; for(int i = 0; i < 2; ++i) { int son = t[cur].nxt[i]; if(inque[son]) { getans = true; break; } if(t[son].end || vis[son]) continue; vis[son] = true; dfs(son); } inque[cur] = false; return; } int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%s", str); Insert(str); } getfail(); dfs(Root); if(getans) puts("TAK"); else puts("NIE"); return 0; }
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/