[Python] Trie solution with detailed explanation
Code:\n\n\n\nclass TrieNode:\n    def __init__(self, val):\n        self.val = val\n        self.child = {}\n        self.last = False\n\nclass WordDictionary: 
**Code:**\n\n```\n\nclass TrieNode:\n    def __init__(self, val):\n        self.val = val\n        self.child = {}\n        self.last = False\n\nclass WordDictionary: # this will serve as  the Trie class\n    def __init__(self):\n        """\n        Initialize your data structure here.\n        """\n        self.root = TrieNode(None)\n        \n    def addWord(self, word: str) -> None:\n        """\n        Adds a word into the data structure.\n        """\n        root = self.root\n        for char in word:\n            if char not in root.child:\n                root.child[char] = TrieNode(char)\n            root = root.child[char]\n        root.last = True\n        \n    def search(self, word: str) -> bool:\n        """\n        Returns if the word is in the data structure. A word could contain the dot character \'.\' to represent any one letter.\n        """\n        \n        # -- helper\n        def dfs(word, root):\n            \n            for i, char in enumerate(word):\n\n                if char == ".":\n                    for child in root.child:\n                        childNode = root.child[child]\n                        if dfs(word[i+1:], childNode):\n                            return True\n                    return False\n\n                else:\n                    if char not in root.child:\n                        return False\n                    root = root.child[char]\n                    \n            return root.last\n        \n        \n        # -- main\n        root = self.root\n        return dfs(word, root) # ----------- [1]\n        \n    \n\n                \n        \n        # NOTE [1]\n        # --------\n        # Why am I passing a root argumnet in addition to the word?\n        # Since we might search words like:\n        #       .ad\n        #       ..d\n        # We would want to begin the search from the first alphabetic letter\n        # after ignoring the dot letters and for that we will need to call\n        # the function recursively but in the recursive scenario, we don\'t want\n        # the trie traversal to happen from the root all over again. Instead,\n        # we want to check the alphabetic part  only and the dots that preceds\n        # that part are irrelevant\n        \n        \n        # NOTE [2]\n        # --------\n        # What\'s up with this additional check: char != "."?\n        # Unlike the traditional trie find() function, the \n        # fact that char is not in root.children is not enough to\n        # return false in this particular example. Because our trie\n        # in this . problem contains words that might begin with\n        # dots -- see figure and thus we only dismiss the word as\n        # not found if the first character of that word is both:\n        #   1- Not found in the self.root.children. AND\n        #   2- First char not a dot\n        \n        \n        \n# Your WordDictionary object will be instantiated and called as such:\n# obj = WordDictionary()\n# obj.addWord(word)\n# param_2 = obj.search(word)\n\n                \n        \n        # NOTE [1]\n        # --------\n        # Why am I passing a root argumnet in addition to the word?\n        # Since we might search words like:\n        #       .ad\n        #       ..d\n        # We would want to begin the search from the first alphabetic letter\n        # after ignoring the dot letters and for that we will need to call\n        # the function recursively but in the recursive scenario, we don\'t want\n        # the trie traversal to happen from the root all over again. Instead,\n        # we want to check the alphabetic part  only and the dots that preceds\n        # that part are irrelevant\n\t\t# SEE SKETCH BELOW FOR FURTHER UNDERSTANDING\n        \n        \n        # NOTE [2]\n        # --------\n        # What\'s up with this additional check: char != "."?\n        # Unlike the traditional trie find() function, the \n        # fact that char is not in root.children is not enough to\n        # return false in this particular example. Because our trie\n        # in this . problem contains words that might begin with\n        # dots -- see figure and thus we only dismiss the word as\n        # not found if the first character of that word is both:\n        #   1- Not found in the self.root.children. AND\n        #   2- First char not a dot\n        \n```\n\n![image](https://assets.leetcode.com/users/images/ee24d7d0-4d8b-44de-8137-9ccd3f35060f_1643254845.3624523.jpeg)\n\n
['Trie', 'Python']