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 }