[luoguP2444] [POI2000]病毒(AC自动机 + dfs)
2017-05-09 15:02
197 查看
先把所有串建一个AC自动机,
如果要找一个不包含任意一个串的串,
说明这个串一直在AC自动机上匹配但匹配不到,
也就是说,匹配时除去val值为1的点,除去fail指针指向val值为1的点,是否有环,dfs即可。
因为val值为1说明匹配上,fail指针指向的点x,根到x所形成的字符串是当前串的后缀,
所以也得除去fail指针指向val值为1的点的点。
——代码
#include <queue> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 30001; int n, cnt; int ch[MAXN << 2][2], fail[MAXN << 2]; char s[MAXN]; bool vis[MAXN << 2], ins[MAXN << 2], val[MAXN << 2]; queue <int> q; inline void insert() { int i, x, len = strlen(s), now = 0; for(i = 0; i < len; i++) { x = s[i] - '0'; if(!ch[now][x]) ch[now][x] = ++cnt; now = ch[now][x]; } val[now] = 1; } inline void make_fail() { int i, x, now; for(i = 0; i <= 1; i++) if(ch[0][i]) q.push(ch[0][i]); while(!q.empty()) { now = q.front(), q.pop(); for(i = 0; i <= 1; i++) { if(!ch[now][i]) { ch[now][i] = ch[fail[now]][i]; continue; } fail[ch[now][i]] = ch[fail[now]][i]; q.push(ch[now][i]); val[ch[now][i]] |= val[fail[ch[now][i]]]; } } } inline bool dfs(int u) { int i, v; ins[u] = 1; for(i = 0; i <= 1; i++) { v = ch[u][i]; if(ins[v]) return 1; if(val[v] || vis[v]) continue; vis[v] = 1; if(dfs(v)) return 1; } ins[u] = 0; return 0; } int main() { int i, j; scanf("%d", &n); for(i = 1; i <= n; i++) { scanf("%s", s); insert(); } make_fail(); if(dfs(0)) puts("TAK"); else puts("NIE"); return 0; }View Code
相关文章推荐
- BZOJ2938 [Poi2000]病毒 解题报告【AC自动机】【DFS】
- BZOJ2938[Poi2000]病毒 AC自动机
- bzoj2938 [Poi2000]病毒 ac自动机
- [bzoj2938][Poi2000]病毒_AC自动机
- BZOJ 2938 [Poi2000]病毒(AC自动机)
- [BZOJ2938][POI2000]病毒(AC自动机+dfs)
- 【bzoj2938】[Poi2000]病毒 AC自动机
- BZOJ_2938_[Poi2000]病毒_AC自动机
- [bzoj2938][Poi2000]病毒 AC自动机
- BZOJ2938 [Poi2000]病毒 【AC自动机】
- BZOJ2938 POI2000 病毒 补全AC自动机 Trie图判环
- 洛古2444 [POI2000]病毒 ac自动机
- bzoj2938 [Poi2000]病毒(AC自动机+DFS找环)
- AC自动机【poi2000】bzoj2938 病毒
- 【bzoj2938】[Poi2000]病毒 AC自动机
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
- BZOJ 2938 [Poi2000]病毒
- 【BZOJ】【P2938】【Poi2000】【病毒】【题解】【AC自动机】
- bzoj2434 [Noi2011]阿狸的打字机 ( AC自动机 & fail树 + 树状数组 + dfs序 )
- BZOJ 2938 Poi2000 病毒 AC自动机+拓扑排序