【学习笔记】字典树(Trie)
【学习笔记】字典树(Trie)
日期:2020-08-25
一、前言

事情是酱紫的,本来本蒟蒻开开心心的用递推\(O(L^2 \log n) \approx 2.5 \times 10^8\)(\(L\)指冰峰文长度)的时间复杂度AC了[NOI2000]古城之谜(不开O2 T了一个点,可能是因为用了cin)。但是,本蒟蒻被dalao吐槽了TAT。说我码风凌乱可以忍(好像确实是),说我不会用Trie也可以忍(毕竟是我学长嘛~)。但是,学无止境。于是,蒟蒻打开了oi-wiki宝典,自行学(xia)习(gao)了字典树。
二、正文
1. 概念
字典树,英文名 trie。顾名思义,就是一个像字典一样的树。
可能有些不太形象,那我们举个栗子叭:比如有一个\(duliu\)、\(dalao\)、\(daunting\)(令人望而生畏的)\(zhltao\),那么我们可以这么存:

仔细看看的话,其实挺像查字典的:我翻开一本如上的字典,翻到\(z\)时,查且只能查到\(zhltao\);翻到\(d\)时,我们可以查\(d-u\)或\(d-a\);以此类推。而存储的形式是棵树,所以美其名曰——字典树(Trie)。
2. 实现
那我们怎么实现呢?当然是定义一个结构体啦!于是有了:
struct node{
int nex[Size][26], cnt;
bool exi[Size];
}
- \(nex[u][c]\)(即\(next\))表示结点\(u\)代表的字符串后面添加一个字符\(c\)形成的字符串的结点。如:\(nex[0][d - a]\)在上图中的值是\(1\),表示(树根到)结点\(0\)表示出来的字符串(空串),再加上一个\(d\)字符后形成的字符串\(d\)的结点编号是\(1\)。
- \(exi[u]\)(即\(exist\))表示以结点\(u\)结尾的字符串是否存在。上图中,\(exi[21]\)应该为真,即存在一个以结点\(21\)结尾的字符串\(zhltao\);而\(exi[20]\)应该为假,即不存在一个以结点\(20\)结尾的字符串\(zhlta\)。
- \(cnt\)(即\(count\)),表示当前最大结点编号(也表示数量)。
- 注意:\(Size\)指的是结点个数,而\(26\)仅可以容纳英文小写字母集,可根据实际要求进行更改。
那么,当需要我们插入单词或查找时,可以定义如下成员函数:
struct node{
void insert(char *s, int l){ //插入
int p = 0;
for (int i = 0; i < l; ++i) {
int c = s[i] - 'a';
if (!nex[p][c]) nex[p][c] = ++cnt; //如果没有,就添加结点
p = nex[p][c];
}
exi[p] = 1;
}
bool find(char *s, int l) { // 查找
int p = 0;
for (int i = 0; i < l; i++) {
int c = s[i] - 'a';
if (!nex[p][c]) return 0;
p = nex[p][c];
}
return exi[p];
}
}
代码不难理解,当然也可以根据实际需要,酌情添加一些信息。字典树(Trie)的基本操作至此就告一段落了。
三、碎碎念
- 学长人真挺好的,\(duliu\)什么的都是开完笑的(为了讲算法需要qwq)。如有雷同,纯属巧合哈哈(大雾

- 如上图,在挂学长博客链接时,那两句诗再次提醒我今天是七夕啊!(孤寡孤寡孤寡
- 哦对了,今天隔壁班有个女生发微信给我,说她要脱单。我送了她一只孤寡青蛙,我真是“汝辈楷模”(狗头保命
路漫漫其修远兮,吾将上下而求索。

浙公网安备 33010602011771号