P2444 [POI2000]病毒 AC自动机

P2444 [POI2000]病毒

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 35000;
 4  
 5 struct Aho_Corasock_Automaton {
 6     struct node {
 7         int fail;  // 失配指针
 8         int son[2];  // 子节点的位置
 9         bool danger;  // 危险标记 
10     }Trie[maxn];
11     int cnt = 0; // Trie指针
12     void insert(char *s) {
13         int len = strlen(s);
14         int now = 0;  // Trie当前指针 
15         for (int i = 0; i < len; ++i) {
16             if (Trie[now].son[s[i]-'0'] == 0) { // 如果没有这个子节点 
17                 Trie[now].son[s[i]-'0'] = ++cnt;  // 构造该节点 
18             }
19             now = Trie[now].son[s[i]-'0']; 
20         }
21         Trie[now].danger = true; 
22     }
23     void get_fail() {  // 构造fail指针 
24         queue<int> que;
25         for (int i = 0; i < 2; ++i) {  // 先提前构造第二层 
26             if (Trie[0].son[i] != 0) {  // 如果存在该节点 
27                 Trie[Trie[0].son[i]].fail = 0;  // fail指向root节点 
28                 que.push(Trie[0].son[i]);  // 加入队列 
29             }
30         }
31         while (!que.empty()) {  // bfs求fail指针 
32             int u = que.front(); que.pop();
33             for (int i = 0; i < 2; ++i) {
34                 if (Trie[Trie[u].fail].danger == true)
35                     Trie[u].danger = true;
36                 if (Trie[u].son[i] != 0) {  // 如果存在该子节点 
37                     // 子节点的fail指针指向当前节点的fail指针指向内容相同的子节点 
38                     Trie[Trie[u].son[i]].fail = Trie[Trie[u].fail].son[i];
39                     que.push(Trie[u].son[i]);  // 加入队列 
40                 }
41                 else {  // 如果不存在这个子节点 
42                     // 当前节点的该子节点指向当前节点的fail指针指向的止隔子节点 
43                     Trie[u].son[i] = Trie[Trie[u].fail].son[i];
44                 }
45             }
46         }
47     }
48 }AC;
49 bool vis[maxn];
50 bool dfs(int u) {
51     if (vis[u] == true) return true;
52     vis[u] = true;
53     if (!AC.Trie[AC.Trie[u].son[0]].danger) {
54         if (dfs(AC.Trie[u].son[0])) {
55             return true;
56         }
57     }
58     if (!AC.Trie[AC.Trie[u].son[1]].danger) {
59         if (dfs(AC.Trie[u].son[1])) {
60             return true;
61         }
62     }
63     vis[u] = false;
64     return false;
65 }
66 char t[maxn];
67 int main() {
68     int n; scanf("%d",&n);
69     for (int i = 1; i <= n; ++i) {
70         scanf("%s",t);
71         AC.insert(t);        
72     }
73     AC.get_fail();
74     if (dfs(0) == true) puts("TAK");  // 从字典树的根结点开始找环
75     else puts("NIE");
76     return 0;
77 }

猜你喜欢

转载自www.cnblogs.com/wstong/p/11759969.html