AC自动机+DFS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <queue> #include <cstring> using namespace std; #define D(x) const int MAX_LEN = 3 * (1e4) + 10; const int MAX_NODE_NUM = MAX_LEN; const int MAX_CHILD_NUM = 2; struct Trie { int next[MAX_NODE_NUM][MAX_CHILD_NUM]; int fail[MAX_NODE_NUM]; int node_cnt; bool vis[MAX_NODE_NUM]; //set it to false bool virus[MAX_NODE_NUM]; int root; void init() { node_cnt = 0; root = newnode(); memset(vis, 0, sizeof(vis)); memset(virus, 0, sizeof(virus)); } int newnode() { for (int i = 0; i < MAX_CHILD_NUM; i++) next[node_cnt][i] = -1; virus[node_cnt++] = false; return node_cnt - 1; } int get_id(char a) { return a - '0'; } void insert(char buf[]) { int now = root; for (int i = 0; buf[i]; i++) { int id = get_id(buf[i]); if (next[now][id] == -1) next[now][id] = newnode(); now = next[now][id]; } virus[now] = true; D(printf("virus[%d] = %d ", now, virus[now])); } void build() { queue<int>Q; fail[root] = root; for (int i = 0; i < MAX_CHILD_NUM; i++) if (next[root][i] == -1) next[root][i] = root; else { fail[next[root][i]] = root; Q.push(next[root][i]); } while (!Q.empty()) { int now = Q.front(); Q.pop(); for (int i = 0; i < MAX_CHILD_NUM; i++) if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; if (virus[fail[next[now][i]]]) virus[next[now][i]] = true; Q.push(next[now][i]); } } } bool dfs(int u) { D(printf("%d ", u)); vis[u] = true; for (int i = 0; i < MAX_CHILD_NUM; i++) { int v = next[u][i]; D(printf(" %d ", v)); if (virus[v]) continue; if (vis[v]) return true; if (dfs(v)) return true; } vis[u] = false; return false; } void debug() { for(int i = 0;i < node_cnt;i++) { printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],virus[i]); for(int j = 0;j < MAX_CHILD_NUM;j++) printf("%2d",next[i][j]); printf("] "); } } }ac; char st[MAX_LEN]; int n; int main() { scanf("%d", &n); ac.init(); for (int i = 0; i < n; i++) { scanf("%s", st); ac.insert(st); } ac.build(); memset(ac.vis, 0, sizeof(ac.vis)); if (ac.dfs(ac.root)) puts("TAK"); else puts("NIE"); return 0; }