OI loves Algorithm(二)——字典树 Trie
更新第二期啦!
Trie 是什么,怎么写
是不是感觉挺熟悉?
没错,以前的一道G题放过这个图片。
可以发现,这棵字典树用边来代表字母,而从根结点到树上某一结点的路径就代表了一个字符串。举个例子, $ 1 \to 4 \to 8 \to 12 $ 表示的就是字符串
caa
。
trie 的结构非常好懂,我们用 $ \delta(u, c) $ 表示结点 $ u $ 的 $ c $ 字符指向的下一个结点,或着说是结点 $ u $ 代表的字符串后面添加一个字符 $ c $ 形成的字符串的结点。( $ c $ 的取值范围和字符集大小有关,不一定是 $ 0 \sim 26 $。)
有时需要标记插入进 trie 的是哪些字符串,每次插入完成时在这个字符串所代表的节点处打上标记即可。——OI Wiki
那字典树怎么写呢?
很简单,只需要实现一棵 26 叉树即可。
不写了,已经被打死了还写什么写
这样,节点诞生!
class trie_node {
public:
trie_node() {
memset(child, -1, sizeof child);
}
int child[128];
} trie[100005];
int node_cnt = 0;
那如何插入一个字符串来更新 Trie 树呢?
从根节点开始,不断来到一个孩子(child[s[i]]
)。
如果没有孩子,则插入一个孩子——
int create() {
return node_cnt++;
}
void construct(string s) {
int node = 0;
for (char ch : s) {
if (trie[node].child[ch] != -1) {
node = trie[node].child[ch];
} else {
node = (trie[node].child[ch] = create());
}
}
}
蛮简单的吧?
板子题
Luogu P2580 于是他错误的点名开始了
Luogu P5755 [NOI2000] 单词查找树
注意了!
P5755 的范围是 $ 1 \leq \sum|S| \leq 100000 $ ,
其中 S 表示字符串。(反正 $ 100000 $ 是可以的)
开大了会 MLE (┭┮﹏┭┮)。今天我就由于开了 $ 500000 $ 爆零了……