https://leetcode.com/problems/add-and-search-word-data-structure-design/#/description
Prefix Tree的构建和查找。
- 插入单词的时候,挨个字符插入即可,记得最后做个标记(表示到这里是一个完整的单词)
- 查找某个单词,由于有通配符
.
的存在,稍微麻烦一些。没碰到.
时,按照前缀树的一般查找方法挨个往下查找即可,碰到.
时,由于它可以代表其他任何一个字符,因此从前缀树当前节点往下的任何一个分支都需要搜索。 - 查找可以用递归实现。
class TrieNode {
public:
bool is_word;
TrieNode* next[26];
TrieNode() : is_word{false} {
for (int i = 0; i < 26; ++i) {
next[i] = NULL;
}
}
};
class WordDictionary {
public:
/** Initialize your data structure here. */
WordDictionary() {
root = new TrieNode();
}
/** Adds a word into the data structure. */
void addWord(string word) {
if (word.empty()) return;
TrieNode* p = root;
for (char c : word) {
if (!p->next[c-'a']) {
p->next[c-'a'] = new TrieNode();
}
p = p->next[c-'a'];
}
p->is_word = true;
}
/** Returns if the word is in the data structure.
A word could contain the dot character '.' to represent any one letter. */
bool search(string word) {
if (word.empty()) return true;
return Search(word, 0, root);
}
private:
TrieNode* root;
bool Search(string& word, int pos, TrieNode* p) {
// 当前状态表示前缀word[0...pos-1]都已经匹配成功
if (pos == word.length()) {
if (!p) return false;
else if (!p->is_word) return false;
else return true;
}
if (word[pos] == '.') {
for (int i = 0; i < 26; ++i) {
if (p->next[i]) {
if ( Search(word, pos+1, p->next[i]) ) return true;
}
}
} else {
int idx = word[pos] - 'a';
if (p->next[idx]) {
return Search(word, pos+1, p->next[idx]);
}
}
return false;
}
};
前缀树的哈希表实现:
class TrieNode {
public:
bool is_word;
unordered_map<int, TrieNode*> next;
TrieNode() : is_word{false} {}
};
class WordDictionary {
public:
/** Initialize your data structure here. */
WordDictionary() {
root = new TrieNode();
}
/** Adds a word into the data structure. */
void addWord(string word) {
if (word.empty()) return;
TrieNode* p = root;
for (char c : word) {
if (p->next.find(c-'a') == p->next.end()) {
p->next[c-'a'] = new TrieNode();
}
p = p->next[c-'a'];
}
p->is_word = true;
}
/** Returns if the word is in the data structure.
A word could contain the dot character '.' to represent any one letter. */
bool search(string word) {
if (word.empty()) return true;
return Search(word, 0, root);
}
private:
TrieNode* root;
bool Search(string& word, int pos, TrieNode* p) {
if (pos == word.length()) {
if (!p) return false;
else if (!p->is_word) return false;
else return true;
}
if (word[pos] == '.') {
for (auto& kv : p->next) {
if ( Search(word, pos+1, kv.second) ) return true;
}
} else {
int idx = word[pos] - 'a';
if (p->next.find(idx) != p->next.end()) {
return Search(word, pos+1, p->next[idx]);
}
}
return false;
}
};