当前位置: 首页 > news >正文

字典树 Trie 乱讲

Trie 是什么

实际上它就是一颗像字典的树,支持插入单词和查询单词个数等操作。

它的边权是某个字符。

比如上图,插入单词 aca 时,我们就可以在 \(5\) 号节点下新建一个节点,边权为 a。而查询是否单词 abs 时,答案为是,因为存在路径 \(1 \to 2 \to 3 \to 4\) 的边权为 abs。

Trie 的实现

插入 & 删除

插入:对于已有的位置,我们直接就可以在原有基础上加;否则就新建一个节点。

删除同理。

// cnt[u]:1 -> u 这条路径以前有几次走过(记录路径对应单词个数)
// trie[u][x]:节点 u 的孩子中,对应边权为 x 的节点编号
void insert(string s){int u = 0;for(int i = 0; i < s.size(); i++){if(!trie[u][s[i] - 'a' + 1]){ // 没有下一个对应节点,新建一个c++;trie[u][s[i] - 'a' + 1] = c;}u = trie[u][s[i] - 'a' + 1]; // 到下一个对应节点cnt[u]++; // 将当前节点的权值 + 1}
}
void del(string s){int u = 0;for(int i = 0; i < s.size(); i++){u = trie[u][s[i] - 'a' + 1]; // 到下一个对应节点cnt[u]--; // 将当前节点的权值 - 1}
}

查询个数

这个过程很像插入,但是如果没有下一个对应节点就说明这个单词不存在,直接返回 \(0\);否则答案为最后一个节点的权值。

void insert(string s){int u = 0;for(int i = 0; i < s.size(); i++){if(!trie[u][s[i] - 'a' + 1]) return 0; // 没有下一个对应节点,也就没有对应单词u = trie[u][s[i] - 'a' + 1]; // 到下一个对应节点}return cnt[u];
}

Trie 的应用

在一些需要求解相同前 / 后缀个数、查找一个字符串是否出现过 / 出现次数时可以用到,但是很少会单独用它。

AC 自动机要用,但我不会。

变式:01 Trie

这个东西就相对常用了。顾名思义,01Trie 就是只维护 \(0\)\(1\) 的 Trie。

看到 \(0\)\(1\),很自然地会想到二进制。我们可以以 01Trie 维护最小 / 大异或值一类问题。

实现大体是一样的,直接贴代码吧。

void insert(ll s){ll u = 0;for(int i = 29; i >= 0; i--){bool x = (s >> i) & 1;if(!zotrie[u][x]){c++;zotrie[u][x] = c;}u = zotrie[u][x];cnt[u]++;}
}
void del(ll s){ll u = 0;for(int i = 29; i >= 0; i--){bool x = (s >> i) & 1;u = zotrie[u][x];cnt[u]--;}
}
ll querymax(ll s){ll ans = 0, u = 0;for(int i = 29; i >= 0; i--){bool x = (s >> i) & 1;ans <<= 1;if(cnt[zotrie[u][!x]]){ // 取反是因为异或最大当然要优先不同位位数最高ans++;u = zotrie[u][!x];}else u = zotrie[u][x];}return ans;
}
ll querymin(ll s){ll ans = 0, u = 0;for(int i = 29; i >= 0; i--){bool x = (s >> i) & 1;ans <<= 1;if(cnt[zotrie[u][x]]){ // 不取反同理u = zotrie[u][x];}else{ans++;u = zotrie[u][!x];}}return ans;
}
http://www.hskmm.com/?act=detail&tid=33245

相关文章:

  • redis和mysql之间的数据一致性
  • ubuntu允许root登录桌面系统
  • 24. 两两交换链表中的节点
  • AI协科学家:技术革命还是安全噩梦?
  • 一个决定
  • 10月17日
  • npm镜像配置
  • 一些特性
  • ubuntu安装mysql
  • 计算机视觉技术与应用深度解析
  • AGC 板刷记录1
  • 2025.10.17总结
  • 记Windows 11环境Rust下载安装配置流程
  • K8s学习笔记(九) job与cronjob - 教程
  • [HZOI]CSP-S模拟33
  • [PaperReading] VLM2Vec-V2: Advancing Multimodal Embedding for Videos, Images, and Visual Documents
  • ShandongCCPC2024
  • 标悬浮展开多级菜单
  • Nimble:让SwiftObjective-C测试变得更优雅的匹配库 - 指南
  • 2025.10.17总结 - A
  • Ubuntu创建python桌面图标
  • 深入解析Pure恶意软件家族:从RAT到构建器再到开发者
  • Ubuntu上配置Flask应用程序的Nginx和uWSGI
  • 实验一 现代c++基础课程
  • 平均融资利率求法及ORACLE语法解析
  • [Linux]如何列出被软链接的文件,列出被链接位置
  • 10.13课后作业
  • 【Linux】基础 I/O - 指南
  • 不情愿算法学概论
  • DIVCNT