算法:Trie树(字典树)

#前缀 #预处理 #基础算法

基本概念

  • 定义:快速插入和查询字符串的数据结构
  • 特点:利用字符串的公告前缀,将字符串组成树形结构
  • 优势:相比map,可以高效查找公共前缀

数据结构准备

  • 头文件
cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;
  • 核心数组定义
cpp 复制代码
const int N = 1e6 + 10;  // 总节点数上限

int tree[N][26];  // Trie树结构,26个字母,
                  // tree[cur][path]从节点cur出发,走path边到达下一节点;
int p[N];         // 记录经过该节点的次数(前缀统计)
int e[N];         // 记录以该节点结尾的单词数量
int idx;          // 当前可用的节点编号

核心操作

插入字符串

cpp 复制代码
void insert(string &s) {
    int cur = 0;        // 从根节点开始
    p[cur]++;           // 根节点经过次数+1
    
    for (auto ch : s) {
        int path = ch - 'a';  // 计算字符对应的路径
        
        // 如果没有这条路,创建新节点
        if (tree[cur][path] == 0) {
            tree[cur][path] = ++idx;
        }
        
        cur = tree[cur][path];  // 移动到下一个节点
        p[cur]++;               // 当前节点经过次数+1
    }
    
    e[cur]++;  // 标记单词结尾
}
复制代码
插入"abc":
根(0) --a--> 节点1 --b--> 节点2 --c--> 节点3
p[0]++, p[1]++, p[2]++, p[3]++
e[3]++  // 标记单词结尾

查询完整单词出现次数

cpp 复制代码
int find(string &s) {
    int cur = 0;
    
    for (auto ch : s) {
        int path = ch - 'a';
        
        // 如果路径不存在,说明单词不存在
        if (tree[cur][path] == 0) {
            return 0;
        }
        
        cur = tree[cur][path];  // 沿着路径移动
    }
    
    return e[cur];  // 返回以该节点结尾的单词数量
}

查询前缀出现次数

cpp 复制代码
int find_pre(string &s) {
    int cur = 0;
    
    for (auto ch : s) {
        int path = ch - 'a';
        
        // 如果路径不存在,说明没有以此前缀开头的单词
        if (tree[cur][path] == 0) {
            return 0;
        }
        
        cur = tree[cur][path];  // 沿着路径移动
    }
    
    return p[cur];  // 返回经过该节点的次数(即前缀数量)
}

使用示例

cpp 复制代码
int main() {
    // 初始化
    idx = 0;
    memset(tree, 0, sizeof(tree));
    memset(p, 0, sizeof(p));
    memset(e, 0, sizeof(e));
    
    // 插入单词
    string word1 = "apple";
    string word2 = "app";
    insert(word1);
    insert(word2);
    
    // 查询
    cout << find("apple") << endl;    // 输出: 1
    cout << find("app") << endl;      // 输出: 1  
    cout << find_pre("app") << endl;  // 输出: 2 (apple和app都以app开头)
    
    return 0;
}

应用场景&注意事项

  • 应用场景 :

  • 单词检索:快速判断单词是否存在

  • 前缀搜索:输入提示、自动补全

  • 词频统计:统计单词出现次数

  • 字典应用:拼写检查、单词推荐

  • 注意事项

  • 节点编号:根节点始终为0,新节点从1开始编号

  • 内存管理:需要预先分配足够大的数组空间

  • 字符范围:示例针对小写字母,其他字符需要调整tree数组第二维大小

  • 初始化:使用前务必清空数组和重置idx;

相关推荐
ACP广源盛1392462567324 分钟前
硬件选型笔记:国产 PCIe Gen2.1 交换芯片 IX6024@ACP,工控与存量设备国产化改造方案评估
笔记·硬件架构·硬件工程·pcie·国产芯片
文人sec1 小时前
SQL基础入门笔记 | 从零基础到掌握核心查询语句
数据库·笔记·sql
Navigator_Z2 小时前
LeetCode //C - 1289. Minimum Falling Path Sum II
c语言·算法·leetcode
CCblandy2 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
himobrinehacken2 小时前
取模运算的汇编奥秘揭秘
c语言·安全
mmmmath_33 小时前
LeetCode.104.二叉树的最大深度
数据结构·leetcode
摇滚侠3 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记
xier_ran3 小时前
【infra之路】AI 编译器学习笔记(六):重拾 C++——lambda 与 MLIR 中的回调
c++·笔记·学习
志尊宝3 小时前
Vue3 零基础每日笔记(078):首屏加载速度优化汇总——清单化方案
笔记
YangYang9YangYan3 小时前
2027供应链计划校招:数学与应用数学专业如何把预测模型讲成业务决策?
人工智能·sql·算法