Trie树-字典树笔记
Trie树-字典树笔记
Trie树是一种高效的存储字符串的数据结构,它将多个字符串的前缀合并在一条边上,每次插入时,都判断当前的树上有无能够重合的前缀,如果没有就单独增加一个节点。通过合并前缀,可以做到快速查找已经优化空间的操作。
下面是使用数组模拟实现Trie树的部分代码:
我们首先定义一个二维数组来构造一个树结构
int tree[N][M];//N表示该树最多有几个节点,M表示每个节点最多伸出多少个枝,即最多有多少个儿子 int idx;//定义编号指针 int cnt[N];//定义计数数组,表示第N个节点到根节点的路径构成的字符串被插入了多少次
trans
转换字符操作:将字符转换为整数,作为树的枝(以字母和数字为例)
int trans(char x) { if (x >= 'A' && x <= 'Z') return x - 'A';//映射大写字母到 0~25 if (x >= 'a' && x <= 'z') return x - 'a' + 26;//映射小写字母到 26~51 if (x >= '0' && x <= '9') return x - '0' + 52;//映射数字到 52~61 }
insert
插入字符串操作:
void insert(char str[]) {//插入str这个字符串 int p = 0, len = strlen(str);//从根节点出发 for (int i = 0; i < len; i++) {//遍历字符串 int c = trans(str[i]);//转换字符映射到整数 if (!tree[p][c])//如果当前节点不存在 c 这个儿子(树枝) tree[p][c] = ++idx;//创建这个枝,然后给予编号 p = tree[p][c];//走到这个节点 cnt[p]++;//当前p节点到根节点的路径构成的字符串被插入次数加1 } }
find
查找字符串操作:(也可以查找前缀)
int find(char str[]) { int p = 0, len = strlen(str);//从根节点开始查找 for (int i = 0; i < len; i++) { int c = trans(str[i]); if (!tree[p][c])//如果当前节点不存在 c 这个儿子 return 0;//返回0,没有找到匹配的浅醉 p = tree[p][c];//存在 c 这个儿子,那么就走到 c 这个儿子节点上 } return cnt[p];//遍历完需要查找的字符串,返回最后一个字符对应的插入的次数 }
以洛谷P8306为例:
#include <stdio.h> #include <iostream> #include <string.h> using namespace std; int n, q, idx; char s[3000010]; int tree[3000010][65], cnt[3000010]; int trans(char x) { if (x >= 'A' && x <= 'Z') return x - 'A'; if (x >= 'a' && x <= 'z') return x - 'a' + 26; if (x >= '0' && x <= '9') return x - '0' + 52; } void insert(char str[]) { int p = 0, len = strlen(str); for (int i = 0; i < len; i++) { int c = trans(str[i]); if (!tree[p][c]) tree[p][c] = ++idx; p = tree[p][c]; cnt[p]++; } } int find(char str[]) { int p = 0, len = strlen(str); for (int i = 0; i < len; i++) { int c = trans(str[i]); if (!tree[p][c]) return 0; p = tree[p][c]; } return cnt[p]; } int main() { int t; scanf("%d", &t); while (t--) { for (int i = 0; i <= idx; i++) for (int j = 0; j <= 64; j++) tree[i][j] = 0; for (int i = 0; i <= idx; i++) cnt[i] == 0; idx = 0;//做完一轮测试后,重新初始化tree scanf("%d %d", &n, &q); for (int i = 0; i < n; i++) { scanf("%s", s); insert(s); } for (int i = 0; i < q; i++) { scanf("%s", s); printf("%d\n", find(s)); } } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程