Skip to content

模型Model

字典树

Trie · Prefix tree

按字符串前缀共享路径组织键集合的树形数据结构。

形式陈述 ​

Trie(前缀树)把一组词组织为有根树:根表示空串,每条边标记一个字母,同一节点的出边标签彼此不同;从根沿路径读出的串对应前缀,终止标记指出哪些前缀本身是已存单词;根也可被标为终止,以表示空字。即使键集合为空,仍保留这个根节点。插入、查询和删除一个长度 m 的词通常访问 O(m+1) 个节点,与集合中词的数量无直接对数因子。设非空的不同前缀共有 p 个,则含根共有 p+1 个节点。若字母表大小为 R,每节点开 R 个孩子槽需 O(pR+R) 空间;只保存存在的边可减少空指针,但每步查找代价取决于孩子字典。

实现字符串键的映射接口时,在每个有终止标记的节点另存一个关联值;根节点也可保存空键的值。插入同一键时覆盖该节点的旧值,查询先检查终止标记,再返回所存值,因此合法值本身不会与“键缺失”混淆。删除键时清除终止标记及其关联值,保留通向其他键的孩子;只回收已无标记且没有孩子的非根节点。枚举时每到一个已标记节点,就输出其路径键与关联值,因而每个现行键值对恰好出现一次。原来的词集合表示相当于所有关联值都取同一个单位值。

直觉

Trie 按字符逐层共享公共前缀,把字符串比较逐字符展开成树导航,避免重复存储相同前缀。从根到某节点的路径标签就是一个前缀,终止标记区分“某词到此结束”和“只是更长词的前缀”。查询时间与键长度成正比而不直接依赖词典大小,代价是节点与稀疏子指针可能占用大量内存。它利用的是字母表结构,不是键的全序比较。

Trie 前缀共享示意图
例子与边界

插入 to 先建立 t→o,并把 o 标为词尾;插入 tea 时复用 t,新建 e→a;插入 ten 时继续复用 te,只新建末尾 n。因此三个词只需五个非根节点。查询 te 能到达节点,但它没有词尾标记,所以精确查询失败;前缀查询则从这里枚举得到 tea,ten。输出这些词的时间还要计入遍历和输出字符,不能把整个枚举都记成 O(2)。

图中还存有 in,inn:in 所在节点既是词尾又有孩子,这说明词尾并不等于叶子。删除 tea 时只去掉末尾 a,不能连同仍被 ten 使用的 te 一起删除;删除 in 时则先清除词尾标记,保留通向 inn 的路径。

字符编码粒度必须一致:按 UTF-8 字节建树与按 Unicode 字符建树会有不同深度和边标签。非空键的操作为 O(m) 还隐含每一步能在 O(1) 时间找到孩子,或已把孩子字典的成本计入;对大 Unicode 字母表直接为每个节点分配稠密数组通常会浪费空间。普通 Trie 的一字符一节点空间较大,压缩 Trie/Patricia 把单分支路径合并;删除时还需保留被其他词共享的前缀。后缀树索引固定文本的全部后缀,并不是把词典 Trie 简单压缩后的同一接口。

推论与应用

词与树定义前缀路径。自动补全、词频和路由最长前缀匹配使用字符 Trie;Aho–Corasick 再加入失败链接实现多模式匹配。二进制 Trie 与 Patricia Trie把整数按 bit 导航,并压缩单分支路径,复杂度通常依赖字长 w 而非字符串字符数。求集合中与查询整数 x 的 XOR 最大值时,可从最高位起优先走与 x 当前位相反的孩子;若该分支不存在才走同位分支,这给出了位 Trie 独有而字符自动补全没有的贪心接口。

x-fast/y-fast Trie进一步在 Word-RAM 上组合前缀哈希与分桶,服务整数前驱问题;其期望或最坏界需要明确哈希与字长模型。FM-index则预处理固定文本的 BWT 与 rank,回答模式区间而不保存字典中每个前缀节点。三条路线共享“前缀”图像,却索引不同对象并提供不同接口。

参考资料
  • Robert Sedgewick and Kevin Wayne, Algorithms, 4th ed., 2011,§5.2 Tries,字符串符号表、前缀匹配与删除。
关系图谱14 个相邻概念 · 3 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
分类位置

上位 / 更一般

下位 / 直接特例

暂未标注直接特例。

类型化关系