trie树

trie字典树目录

本文用于整理 ACM trie树论相关知识点与题目,方便自己和队友查阅。
持续更新中……

一、Trie 树是什么

Trie 树,又叫字典树、前缀树,是一种用于高效存储和查找字符串集合的多叉树结构。

它的核心思想是:把字符串的公共前缀合并到同一条路径上,从而减少存储空间、加快查询速度。

例如插入 cat、car、card、dog 后,Trie 树长这样:

        root
       /    \
      c      d
      |      |
      a      o
      |      |
      t/r    g
          \
           d

可以看到 cat、car、card 共享了前缀 ca,节省了空间。

二、适用场景

  • 字符串集合的插入与查询
  • 前缀查询:判断是否存在以某串为前缀的字符串
  • 异或最大值:01-Trie(把数字按二进制插入)
  • 字符串排序:按字典序输出
  • AC 自动机:Trie + KMP 思想
  • 单词统计:统计某字符串出现次数

三、核心操作

1. 插入字符串

从根节点出发,逐字符向下走:

  • 如果对应子节点不存在,就新建一个
  • 如果存在,就复用
  • 走到最后一个字符时,在末尾节点打上标记(表示这是一个完整单词)

2. 查询字符串

从根节点出发,逐字符向下走:

  • 如果中途某个字符对应的子节点不存在 → 字符串不在集合中
  • 如果能走到最后,并且末尾节点有标记 → 字符串存在
  • 如果能走到最后,但末尾节点没有标记 → 只是前缀,不是完整单词

3. 查询前缀

和查询字符串类似,但不需要检查末尾标记,只要能走完整个前缀即可。

四、模板代码

以「小写字母字符串」为例,字符集大小 26。

数组版(推荐,速度快)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;   // 最大节点数
const int M = 26;        // 字符集大小

int trie[N][M];          // trie[p][c] 表示节点 p 走字符 c 到达的节点编号
int cnt[N];              // cnt[p] 表示以节点 p 结尾的单词数量
int tot = 0;             // 当前节点总数,根节点编号为 0

// 插入字符串 s
void insert(const string &s)
{
    int p = 0;                  // 从根节点出发
    for (char ch : s)
    {
        int c = ch - 'a';
        if (!trie[p][c])        // 子节点不存在
            trie[p][c] = ++tot; // 新建节点
        p = trie[p][c];         // 向下走
    }
    cnt[p]++;                   // 末尾节点计数 +1
}

// 查询字符串 s 出现的次数
int query(const string &s)
{
    int p = 0;
    for (char ch : s)
    {
        int c = ch - 'a';
        if (!trie[p][c]) return 0; // 走不下去,不存在
        p = trie[p][c];
    }
    return cnt[p];
}

// 查询是否存在以 s 为前缀的字符串
bool queryPrefix(const string &s)
{
    int p = 0;
    for (char ch : s)
    {
        int c = ch - 'a';
        if (!trie[p][c]) return false;
        p = trie[p][c];
    }
    return true;
}

六、经典例题

1. 前缀匹配

维护一个字符串集合,支持插入字符串、查询某字符串出现次数。

-- 洛谷 P8306 【模板】字典树

  • 思路: 给定n个字符串,找含前缀的模板串的文本串数量
  • 做法:依次加入trie树中,维护维护一个字符串集合,并更新含有该字符的数量

2. 01字典树

-- The XOR Largest Pair(01-Trie 经典题)

  • 思路: 给定 n 个数,求任意两数异或的最大值。

  • 做法:把每个数按二进制(从高位到低位)插入 01-Trie,查询时贪心走相反位。

-- 异或盒子(01-Trie + 全局 +1)

  • 思路:给定 n 个数,求任意两数异或的最大值。
  • 做法:把每个数插入后进行维护trie数,全局加一:从根开始,交换左右子树(第 b 位翻转),对新的左子树递归处理进位。

3. 字符串统计(未完成)

七、总结

要点 内容
本质 用公共前缀合并路径的多叉树
核心操作 插入、查询、前缀查询
时间复杂度 每次操作 O(L)
典型应用 字符串统计、前缀匹配、01-Trie 异或最大值
常见变体 01-Trie、可持久化 Trie、AC 自动机
posted @ 2026-09-24 12:43  leaderling  阅读(15)  评论(0)    收藏  举报