hihocoder 1036 (Trie图)

题目链接

AC代码:

  1 #include<set>
  2 #include<map>
  3 #include<cmath>
  4 #include<queue>
  5 #include<cstdio>
  6 #include<vector>
  7 #include<string>
  8 #include<cstdlib>
  9 #include<cstring>
 10 #include<iostream>
 11 #include<algorithm>
 12 using namespace std;
 13 
 14 #define mem(a, b) (memset(a, b, sizeof(a)))
 15 #define pb push_back
 16 #define all(v) v.begin(), v.end()
 17 #define rall(v) v.rbegin(), v.rend()
 18 #define rep(i, m) for (int i = 0; i < (int)(m); i++)
 19 #define rep2(i, n, m) for (int i = n; i < (int)(m); i++)
 20 typedef long long LL;
 21 typedef pair<int, int> pii;
 22 
 23 const int oo = (int) 1e9;
 24 const double PI = 2 * acos(0);
 25 const double eps = 1e-9;
 26 const int MAX_N = 1000010;
 27 
 28 struct TrieNode {
 29     TrieNode *next[26]; // 若有子节点,则为子节点,否则为该节点后缀指向节点
 30     TrieNode *suffix;
 31     bool marked;
 32     TrieNode() {
 33         for (int i = 0; i < 26; ++i) {
 34             next[i] = NULL;
 35         }
 36         suffix = NULL;
 37         marked = false;
 38     }
 39 };
 40 
 41 struct TrieGragh {
 42     TrieNode *root;
 43     TrieGragh() { // 略去析构函数
 44         root = new TrieNode;
 45         root->suffix = root;
 46     }
 47 
 48     void insert(const char *s) {
 49         int pos = 0;
 50         TrieNode *nodePos = root;
 51         int sz = strlen(s);
 52         while (pos < sz) {
 53             int id = s[pos] - 'a';
 54             if (nodePos->next[id] == NULL) {
 55                 nodePos->next[id] = new TrieNode;
 56             }
 57             nodePos = nodePos->next[id];
 58             ++pos;
 59         }
 60         nodePos->marked = true;
 61     }
 62 
 63     void generateNext() {
 64         queue<TrieNode *> nodeQueue;
 65         for (int i = 0; i < 26; ++i) {
 66             if (root->next[i] != NULL) { // 初始化
 67                 nodeQueue.push(root->next[i]); // 子节点
 68                 root->next[i]->suffix = root;
 69                 if (root->marked)
 70                     root->next[i]->marked = true;
 71             } else {
 72                 root->next[i] = root;
 73             }
 74         }
 75 
 76         while (!nodeQueue.empty()) {
 77             TrieNode *node = nodeQueue.front();
 78             nodeQueue.pop();
 79 
 80             // 对于该节点,每个子节点压入队列并求后缀
 81             // 若父节点通过ch指向子节点,则子节点后缀 = 父节点后缀通过ch指向的节点
 82             for (int i = 0; i < 26; ++i) {
 83                 TrieNode *child = node->next[i];
 84                 if (child == NULL) {
 85                     node->next[i] = node->suffix->next[i];
 86                     continue;
 87                 }
 88                 child->suffix = node->suffix->next[i];
 89                 if (child->suffix->marked) // 后缀节点为已标记节点的节点也要标记
 90                     child->marked = true;
 91                 if (!child->marked) // 已标记节点的子节点无需再看
 92                     nodeQueue.push(child);
 93             }
 94         }
 95     }
 96 };
 97 
 98 bool match(TrieGragh *trieGragh, char *article) {
 99     int pos = 0;
100     TrieNode *nodePos = trieGragh->root;
101     if (nodePos->marked)
102         return true;
103     int sz = strlen(article);
104     while (pos < sz) {
105         int id = article[pos] - 'a';
106         if (id < 0 || id > 26) {
107             nodePos = trieGragh->root;
108             ++pos;
109             continue;
110         }
111         nodePos = nodePos->next[id];
112         if (nodePos->marked)
113             return true;
114         ++pos;
115     }
116     return false;
117 }
118 
119 char str[MAX_N];
120 int main(void) {
121     int N;
122     scanf("%d", &N);
123     TrieGragh *trieGragh = new TrieGragh;
124     for (int i = 0; i < N; ++i) {
125         scanf("%s", str);
126         trieGragh->insert(str);
127     }
128 
129     trieGragh->generateNext();
130     scanf("%s", str);
131     if (match(trieGragh, str))
132         printf("YES
");
133     else
134         printf("NO
");
135 
136     return 0;
137 }
View Code
原文地址:https://www.cnblogs.com/Stomach-ache/p/4425927.html