【BZOJ2938】[POI2000]病毒
阿新 • • 發佈:2019-01-08
節點 ostream max puts www. push stream bool space
【BZOJ2938】[POI2000]病毒
題面
bzoj 洛谷
題解
現在看到字符串的題面就是$AC$自動機23333。。。(以前是哈希)
這題和普通的$AC$自動機題有些許不同
這題的文本串並未給出來
怎麽辦呢?
想一下,如果一個字符串匹配不到任何東西的話,會怎麽樣
是不是會一直在裏面打轉轉?
所以就在$trie$圖中找有沒有沒有環就行了
註意經過病毒串前綴的節點不可訪問
代碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <queue> using namespace std; const int MAX_N = 3e4 + 5; int c[MAX_N][2], fail[MAX_N], End[MAX_N], tot; void insert(char *s) { int o = 0; for (int i = 0, l = strlen(s); i < l; i++) { int son = s[i] - ‘0‘; if (!c[o][son]) c[o][son] = ++tot; o = c[o][son]; } End[o] = 1; } void build() { static queue<int> que; for (int i = 0; i < 2; i++) if (c[0][i]) que.push(c[0][i]), fail[c[0][i]] = 0; while (!que.empty()) { int o = que.front(); que.pop(); for (int i = 0; i < 2; i++) if (c[o][i]) fail[c[o][i]] = c[fail[o]][i], End[c[o][i]] |= End[fail[c[o][i]]], que.push(c[o][i]); else c[o][i] = c[fail[o]][i]; } } bool ins[MAX_N], vis[MAX_N]; void dfs(int x) { if (ins[x]) puts("TAK"), exit(0); if (vis[x] || End[x]) return ; vis[x] = ins[x] = 1; dfs(c[x][0]); dfs(c[x][1]); ins[x] = 0; } int N; char s[MAX_N]; int main () { scanf("%d", &N); for (int i = 1; i <= N; i++) scanf("%s", s), insert(s); build(); dfs(0); puts("NIE"); return 0; }
【BZOJ2938】[POI2000]病毒