【学习笔记】字典树(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)的基本操作至此就告一段落了。

三、碎碎念

  1. 学长人真挺好的,\(duliu\)什么的都是开完笑的(为了讲算法需要qwq)。如有雷同,纯属巧合哈哈(大雾
  2. 如上图,在挂学长博客链接时,那两句诗再次提醒我今天是七夕啊!(孤寡孤寡孤寡
  3. 哦对了,今天隔壁班有个女生发微信给我,说她要脱单。我送了她一只孤寡青蛙,我真是“汝辈楷模”(狗头保命
posted @ 2020-08-25 22:37  _lhy  阅读(256)  评论(1)    收藏  举报