可爱的Trie树
鉴于ducati的建议下,讲一下trie树(见书p77)
Definition 定义
—Trie又被称为前缀树、字典树,所以当然是一棵树。树中的每一条边上都标识有一个字符。这些字符可以是任意一个字符集中的字符。比如对于都是小写字母的字符串,字符集就是’a’-‘z’;对于都是数字的字符串,字符集就是’0’-‘9’;对于二进制字符串,字符集就是0和1。
初始化
- 一棵空trie仅包含一个根节点,该点的字符指针均指向NULL
插入 Insert
- 当需要插入一个字符串S时,我们令一个指针P起初指向根节点。然后依次扫描S中的每个字符c:
1.若P的c字符指针指向一个已经存在的节点Q,则令P=Q。
2.若P的c字符指针指向空,则新建一个节点Q,令P的c字符指针指向Q,然后令P=Q。
非常地不好理解?让我用大白话来讲一遍:
一个字符串S(即一个单词),从左到右扫描这个单词,如果字母在相应根节点下没出现过,就插入这个字母;如果出现过,就沿着trie树往下走。单词的下一个字母也是同理。(有木有好理解一点)
查找 Search
当需要检索一个字符串S在Trie中是否存在时,我们令一个指针P起初指向根节点,然后依次扫描S中地每个字符c:
- 若P的c字符指针指向空,则说明S没有被插入过Trie,结束检索。
- 若P的c字符指针指向一个已经存在的节点Q,则令P=Q。
当S中的字符扫描完毕时,若当前节点P被标记为一个字符串的末尾,则说明S在Trie中存在,else 说明S没有被插入过Trie。
还是用大白话翻译一下:
从左往右依次扫描S中的每个字符c,顺着Trie树往下,能找到这个字母,往下走,找不到这个字母就结束查找,即没有这个前缀;前缀扫完了,表示有这个前缀。
下面代码:
//Trie
int trie[SIZE][26],tot=1; //初始化,假设字符串由小写字母构成;
void insert(char*str) { //insert字符串;
int len=strlen(str),p=1;
for (int k=0;k<len;k++)
{
int ch=str[k]-'a';
if (trie[p][ch]==0)
trie[p][ch]=++tot;
p=trie[p][ch];
}
end[p]=true;
}
bool search (char*str) { //search字符串;
int len=strlen(str),p=1;
for (int k=0;k<len;k++) {
p=trie[p][str[k]-'a'];
if (p==0)
return false;
}
return end[p];
}
当然这样讲是大不能让读者完全理解trie树的,于是举个栗子:
CF1446c
这题是ducati神犇推荐的%%%
插一个小花絮,我一开始看题的时候没有看到有翻译,对着英文看完写完的qaq(眼神不好
题意
给定你一个序列a,对于每个i,它会向序列中的满足ai⊕aj最小的j连双向边,并且如果j也向i连了边,只算一条边。现在要让你删去序列中的一些数,使得最后形成的图是一颗树,输出最少需要删除几个数。
题解
首先可以判断这是张图,而且这张图可能有环或者不连通。那我们就要使其组成的图是一棵树,就要删除一些元素。
思路说来就来:
先在每个数里插入一棵trie树,对于任意节点,若左儿子和右儿子的size都大于1,则会形成两个子图;所以我们就要删除一些节点,使其中一个儿子的size=1(这里用dp就行)。
这边放一下部分代码~~(一开始写的时候insert不会写,后来补上了就ac了qwq~~
int read()
{
int n=0,f=-1;
char ch;
while((ch=getchar())<'0' || ch>'9')
{
if(ch=='-') f=-1;
}
while(ch>='0' && ch<='9') {
n=(n<<3)+(n<<1)+(ch^48);
ch=getchar();
}
return n*f;
}
/*void insert(int &n,int v,int d)
当时没补就保存了所以看官自行脑部吧qaq*/
void dp(int n,int d)
{
if(!n||d==0)
return;
dp(ls[n], d-1);
dp(rs[n], d-1);
if(!ls[n])
f[n]=f[rs[n]];
else if(!rs[n])
f[n]=f[ls[n]];
else
f[n]=max(f[ls[n]],f[rs[n]])+1;
}
signed main()
{
z=read();
for(int i=1;i<=z;i++)
insert(rt,read(),31);
dp(rt,31);
cout<<z-f[rt]<<endl;
}
trie树其实也不很难的亚子~
谢谢大家看完qwq