Design Add and Search Words Data Structure
Design a data structure that supports adding new words and finding if a string matches any previously added string. Implement the `WordDictionary` class: `WordDictionary()` Initializes the object. `void addWord(word)` Adds `word` to the data structure, it can be matched later. `bool search(word)` Returns `true` if there is any string in the data structure that matches `word` or `false` otherwise. `word` may contain dots `'.'` where dots can be matched with any letter.
Examples
Constraints
1 <= word.length <= 25word in addWord consists of lowercase English letters.word in search consist of '.' or lowercase English letters.There will be at most 2 dots in word for search queries.At most 10^4 calls will be made to addWord and search.
Trie with DFS for Dot Wildcards
Approach
Adding words is identical to standard Trie insertion. For searching, if we encounter a regular character, we traverse the child node as usual. If we encounter a '.' wildcard, we must explore ALL possible child nodes. We can use a recursive Depth-First Search (DFS) helper function. If `dfs` returns true for any child path, we return true. If we reach the end of the word, we check `isEndOfWord`.
Complexity Analysis
Due to the wildcard '.', search can potentially branch to all 26 children at each step, though in practice it is constrained by existing paths.
class TrieNode { TrieNode[] children; boolean isEndOfWord; public TrieNode() { children = new TrieNode[26]; isEndOfWord = false; }}
class WordDictionary { private TrieNode root;
public WordDictionary() { root = new TrieNode(); } public void addWord(String word) { TrieNode curr = root; for (char c : word.toCharArray()) { int index = c - 'a'; if (curr.children[index] == null) { curr.children[index] = new TrieNode(); } curr = curr.children[index]; } curr.isEndOfWord = true; } public boolean search(String word) { return dfs(word, 0, root); } private boolean dfs(String word, int index, TrieNode node) { if (index == word.length()) { return node.isEndOfWord; } char c = word.charAt(index); if (c == '.') { // Explore all possible children for (int i = 0; i < 26; i++) { if (node.children[i] != null && dfs(word, index + 1, node.children[i])) { return true; } } return false; } else { // Standard search int childIndex = c - 'a'; if (node.children[childIndex] == null) { return false; } return dfs(word, index + 1, node.children[childIndex]); } }}