Design Add and Search Word Data Structure
Problem
Design a data structure that supports adding new words and searching for existing words.
Implement the WordDictionary class:
void addWord(word)Addswordto the data structure.bool search(word)Returnstrueif there is any string in the data structure that matcheswordorfalseotherwise.wordmay contain dots'.'where dots can be matched with any letter.
Examples
Example 1:
Input:
["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
[[],["day"],["bay"],["may"],["say"],["day"],[".ay"],["b.."]]
Output:
[null, null, null, null, false, true, true, true]
Explanation:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord("day");
wordDictionary.addWord("bay");
wordDictionary.addWord("may");
wordDictionary.search("say"); // return false
wordDictionary.search("day"); // return true
wordDictionary.search(".ay"); // return true
wordDictionary.search("b.."); // return true
Constraints
1 <= word.length <= 20wordinaddWordconsists of lowercase English letters.wordinsearchconsist of'.'or lowercase English letters.- There will be at most
2dots inwordforsearchqueries. - At most
10,000calls will be made toaddWordandsearch.
You should aim for a solution with O(n) time for each function call and O(t + n) space, where n is the length of the string and t is the total number of nodes created in the Trie.
Solution
struct Node {
std::unordered_map<char, Node*> children;
bool end_of_word;
Node() = default;
~Node() {
for (auto &[_, child] : children) {
delete child;
}
}
};
class WordDictionary {
Node *root;
public:
WordDictionary() {
root = new Node();
}
~WordDictionary() { delete root; }
void addWord(const string &word) {
Node *current = root;
for (const auto &c : word) {
if (!current->children.contains(c)) {
current->children[c] = new Node();
}
current = current->children[c];
}
current->end_of_word = true;
}
bool search(const string &word) {
std::function<bool(Node*, std::size_t)> dfs;
// DFS checks if word[i:] matches any path starting from this node
dfs = [&](Node *node, std::size_t i) -> bool {
// Reached end of word, check if we are at terminal node
if (i == word.size()) { return node->end_of_word; }
char c = word[i];
if (c == '.') {
// Wildcard, check if any child has solution
for (auto &[_, child] : node->children) {
if (dfs(child, i + 1)) {
return true;
}
}
return false;
}
if (!node->children.contains(c)) {
return false;
}
return dfs(node->children[c], i + 1);
};
return dfs(root, 0);
}
};