211. 添加与搜索单词 - 数据结构设计

import collections

class TrieNode:
    """Trie 树节点类"""
    def __init__(self):
        # 子节点字典:键是字符,值是对应的 TrieNode 子节点
        # 使用 defaultdict 可以稍微简化 addWord,但普通 dict 更清晰
        self.children = {} 
        # 标记:从根节点到当前节点是否形成一个完整的单词
        self.is_end = False 

class WordDictionary:
    """实现添加和搜索单词(含通配符)的数据结构"""

    def __init__(self):
        """
        初始化数据结构。
        """
        # 创建 Trie 树的根节点
        self.root = TrieNode()

    def addWord(self, word: str) -> None:
        """
        将 word 添加到数据结构中,之后可以对它进行匹配。
        """
        # 从根节点开始
        cur = self.root
        # 遍历单词中的每个字符
        for char in word:
            # 如果字符对应的子节点不存在...
            if char not in cur.children:
                # ...则创建一个新的 TrieNode 作为子节点
                cur.children[char] = TrieNode()
            # 移动到子节点
            cur = cur.children[char]
        # 单词遍历结束后,将当前节点的 is_end 标记设为 True
        # 表示从根到此节点是一个完整的单词
        cur.is_end = True

    def search(self, word: str) -> bool:
        """
        搜索 word 是否在数据结构中。
        word 可能包含 '.',每个 '.' 可以匹配任意一个字母。
        返回 True 如果 word 在结构中匹配成功,否则返回 False。
        """
        
        # 定义内部的 DFS 辅助函数
        # node: 当前遍历到的 Trie 节点
        # index: 当前正在匹配 word 中的字符索引
        def dfs_help(node: TrieNode, index: int) -> bool:
            
            # --- 递归基准情况 (Base Case) ---
            # 如果 index 到达了 word 的末尾
            if index == len(word):
                # 只有当当前 Trie 节点标记为单词结尾时,才算真正匹配成功
                return node.is_end 

            # --- 递归步骤 (Recursive Step) ---
            # 获取当前需要匹配的字符
            char = word[index]

            # 情况 1: 当前字符是通配符 '.'
            if char == '.':
                # 需要尝试当前节点的所有子路径
                # 如果 children 为空,则循环不会执行,直接返回 False (见循环后的 return)
                for child_node in node.children.values():
                    # 对每个子节点,递归调用 dfs_help 尝试匹配 word 的剩余部分 (index + 1)
                    # 只要有任意一个子路径能够成功匹配,整个 search 就成功了
                    if dfs_help(child_node, index + 1):
                        return True
                # 如果遍历完所有子节点都没有找到成功的路径,则说明此路不通
                return False
            # 情况 2: 当前字符是普通字母
            else:
                # 检查该字母是否存在于当前节点的子节点中
                if char in node.children:
                    # 如果存在,则沿着该字母对应的子节点继续向下递归搜索
                    return dfs_help(node.children[char], index + 1)
                else:
                    # 如果该字母对应的子节点不存在,说明无法匹配,返回 False
                    return False

        # --- search 方法的主调用 ---
        # 从 Trie 树的根节点 (self.root) 和单词的起始索引 (0) 开始执行 DFS
        return dfs_help(self.root, 0)

# 示例用法:
# obj = WordDictionary()
# obj.addWord("bad")
# obj.addWord("dad")
# obj.addWord("mad")
# print(obj.search("pad")) # 输出: False
# print(obj.search("bad")) # 输出: True
# print(obj.search(".ad")) # 输出: True
# print(obj.search("b..")) # 输出: True



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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值