class TrieNode:
    def __init__(self, val = ''):
        self.child = []
        self.is_word = False
        self.val = val
        self.child_map = {}
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word: str) -> None:
        parent_node = self.root
        for idx, letter in enumerate(word):
            if letter not in parent_node.child_map:
                new_node = TrieNode(letter)
                parent_node.child.append(new_node)
                parent_node.child_map[letter] = len(parent_node.child) - 1
                parent_node = new_node
            else:
                idx = parent_node.child_map[letter]
                parent_node = parent_node.child[idx]
        parent_node.is_word = True

    def search(self, word: str) -> bool:
        def subsearch(node, word) -> bool:
            parent_node = node
            if len(word) == 0:
                return parent_node.is_word
            ch = word[0]
            rlt = False
            if ch == '.':
                flag = 0
                for child in parent_node.child_map:
                    idx = parent_node.child_map[child]
                    r = subsearch(parent_node.child[idx], word[1:])
                    if r == True: flag = 1
                if flag == 1:
                    return True
                else:
                    return False
            else:
                if ch not in parent_node.child_map:
                    return False
                else:
                    idx = parent_node.child_map[ch]
                    return subsearch(parent_node.child[idx], word[1:])
        return subsearch(self.root, word)

    def startsWith(self, prefix: str) -> bool:
        parent_node = self.root
        for idx, letter in enumerate(prefix):
            if letter not in parent_node.child_map:
                return False
            idx = parent_node.child_map[letter]
            parent_node = parent_node.child[idx]
        return True
class WordDictionary:
    def __init__(self):
        self.tree = Trie()

    def addWord(self, word: str) -> None:
        self.tree.insert(word)

    def search(self, word: str) -> bool:
        return self.tree.search(word)


# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)