Problem of The Day: Design Add and Search Words Data Structure
Problem Statement

Intuition
Upon seeing this problem, I think a trie data structure would be a suitable choice. It’s efficient for storing and searching words with a common prefix. However, the challenge here is dealing with wildcard characters (‘.’). We’ll need to implement a search function that handles these wildcards appropriately.
Approach
I’ll use a trie to store the words. When adding a word, I’ll traverse the trie character by character, creating nodes as needed. For searching, I’ll recursively traverse the trie while handling wildcards by exploring all possible branches at each wildcard encountered.
Complexity
- 
    Time complexity: 
- For adding a word: O(n), where n is the length of the word.
- For searching:
    - Worst-case without wildcards: O(m), where m is the length of the word being searched.
- With wildcards: It depends on the number of wildcard characters and the branching factor of the trie. It can be quite high, possibly exponential in the worst case.
 
- Space complexity: O(n) where n here is the number of characters in all words combinedß
Code
class WordDictionary:
    def __init__(self):
        self.root = {}
    def addWord(self, word: str) -> None:
        curr = self.root
        for c in word:
            if c not in curr:
                curr[c] = {}
            curr = curr[c]
        curr['#'] = True
    def search(self, word: str) -> bool:
        curr = self.root
        for i, c in enumerate(word):
            if c == '.':
                for node in curr.keys():
                    if node == '#':
                        continue
                    if self.search(word[:i] + node + word[i+1:]):
                        return True
            if c not in curr:
                return False
            curr = curr[c]
        return '#' in curr
# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)
Editorial Solution
Approach 1: Trie
class WordDictionary:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.trie = {}
    def addWord(self, word: str) -> None:
        """
        Adds a word into the data structure.
        """
        node = self.trie
        for ch in word:
            if not ch in node:
                node[ch] = {}
            node = node[ch]
        node['$'] = True
    def search(self, word: str) -> bool:
        """
        Returns if the word is in the data structure. A word could contain the dot character '.' to represent any letter.
        """
        def search_in_node(word, node) -> bool:
            for i, ch in enumerate(word):
                if not ch in node:
                    # if the current character is '.'
                    # check all possible nodes at this level
                    if ch == '.':
                        for x in node:
                            if x != '$' and search_in_node(word[i + 1:], node[x]):
                                return True
                    # If no nodes lead to an answer
                    # or the current character != '.'
                    return False
                # If the character is found
                # go down to the next level in trie
                else:
                    node = node[ch]
            return '$' in node
        return search_in_node(word, self.trie)