-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtrie_graph.cpp
More file actions
129 lines (123 loc) · 3.56 KB
/
trie_graph.cpp
File metadata and controls
129 lines (123 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
/**
* Describle: Given an array of illegal words, and a string, decide weather the
* string contains any of illegal words.
* Words is composed of a-z.
*/
class Solution {
public:
// The trie tree node
struct Node {
bool tag = false; // indicate a complete word
// the subtree pointer
vector<struct Node*> next = vector<struct Node*>(26, nullptr);
// indicate the source of the node
// True: from the trie tree
// False: from the trie network
vector<bool> base = vector<bool>(26, false);
// the traback position
struct Node *missed_ptr;
};
vector<string> dic;
Node *root = nullptr;
Solution(vector<string> &dic) {
this->dic.swap(dic);
buildTrieTree();
buildTrieGraph();
}
// valid the given article
bool valid(string &article) {
Node *cur = root;
int idx;
for (auto c : article) {
idx = c - 'a';
cur = cur->next[idx];
if (cur->tag) {
return true;
}
}
return false;
}
void buildTrieGraph() {
queue<Node*> node_q;
node_q.push(root);
root->missed_ptr = root;
for (int i = 0; i < 26; ++i) {
if (!root->next[i]) {
root->next[i] = root;
} else {
root->next[i]->missed_ptr = root;
}
}
// WFS scan the trie tree
while (!node_q.empty()) {
auto front = node_q.front();
node_q.pop();
for (int i = 0; i < 26; ++i) {
if (front->base[i]) {
auto ptr = front->next[i];
for (int j = 0; j < 26; ++j) {
if (!ptr->next[j]) {
// build the reference for each missed path
ptr->next[j] = ptr->missed_ptr->next[j];
} else {
// get the track back node
ptr->next[j]->missed_ptr = ptr->missed_ptr->next[j];
// if the track back node is a word end, current
// node also a word end
if (ptr->next[j]->missed_ptr->tag) {
ptr->next[j]->tag = true;
}
}
}
node_q.push(ptr);
}
}
}
}
void buildTrieTree() {
root = new Node();
for (auto &str : dic) {
insertWord(root, str, 0);
}
}
void insertWord(Node *ptr, string& word, size_t pos) {
if (pos == word.size()) {
ptr->tag = true;
return;
}
int idx = word[pos] - 'a';
if (!ptr->next[idx]) {
ptr->next[idx] = new Node();
ptr->base[idx] = true;
}
insertWord(ptr->next[idx], word, pos + 1);
}
};
/**
* Input:
* n: the number of the illegal word.
* n line: n illegal word
* the validate string
* Output: weather the string contains illegal words, if so print 'YES', or 'NO'
*
* Note: all string composed of a-z
*/
int main() {
int n;
vector<string> dic;
string article;
cin >> n;
dic = vector<string>(n);
for (auto &str : dic) {
cin >> str;
}
Solution so(dic);
cin >> article;
auto rst = so.valid(article);
cout << (rst? "YES" : "NO") << endl;
return 0;
}