数据结构——字典树

NO.1 定义

字典树又称单词查找树, T r i e Trie Trie 树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

它具体是什么样的呢?

它的点用来保存每一个节点编号,以及有无在此节点结束的字符串。

它的边用来保存字符。

从根节点到每一个子节点的路径上字符所组成的即为一个字符串。

NO.2 插入

字典树共应用两个函数,插入和检索。

插入,顾名思义即为在字典树中插入一个字符串,从根节点出发,根据字符串上的每一个字符向下搜,如果指向空则另开边存储字符。

需要注意,我们需运用一个数组来记录此节点是否是一个字符串的末尾,不然无法判断在字典树上是否存在此字符串。

Code

void Insert(char *str){//将字符串以指针形式传入,操作时直接影响实参
	int p=1,len=strlen(str);
	for(int i=0;i<len;i++){
		int ch=str[i]-'a';
		int q=Trie[p][ch];
		if(!q){//判断是否存在保存当前字符的边
			Trie[p][ch]=q=++cnt;
		}
		p=q;
	}
	End[p]++;//保存结尾
}

NO.3 检索

检索,指判断字典树中是否存在一个字符串。

依旧从根节点出发,根据字符串上的每一个字符向下搜,如果没有边对应字符串中的字符或搜到末尾没有标记,则说明没有此字符串在字典树中,反而有之。

Code

bool search(string s){//依旧传入字符串地址
    int p=1,len=s.length();
    for(int i=0;i<len;i++){
        int ch=s[i]-'0'; 
        p=Trie[p][ch];
        if(!p){//判断有无此边
                return 0;
	}
    }
    return en[p];//判断此边是否是一个字符串结尾
}

NO.4 例题

The XOR-longest Path

Link

题目描述

给定一棵 n n n 个点的带权树,求树上最长的异或和路径。

输入格式

第一行一个整数 n n n ,接下来 n − 1 n-1 n1 行每行三个整数 u , v , w u,v,w u,v,w ,表示 u , v u,v u,v 之间有一条长度为 w w w 的边。

输出格式

输出一行一个整数,表示答案。

样例

样例输入

4
1 2 3
2 3 4
2 4 6

样例输出

7

思路

题目解释的很清楚,求树上一段路径的数异或的最大值。

因为 a ⊕ a = 0 a \oplus a=0 aa=0

所以我们可求得根节点到每一节点异或值,设为 d a d_a da

设要求的路径端点为 x , y x,y x,y,则路径上的异或值为 d x ⊕ d y d_x \oplus d_y dxdy

根据每两个端点的异或值的二进制数建字典树,因异或,每一数位的数字相反才为 1 1 1,则每次判断字符时去与它想法的一边即可。

Code
void Insert(ll x){
	ll p=1;
	for(int i=30;i>=0;i--){
		ll ch=x>>i&1;
		if(!Trie[p][ch]){
			Trie[p][ch]=++cnt;
		}
		p=Trie[p][ch];
	}
	End[p]=1;
}

ll Search(ll x){
	ll p=1,ans=0,de=30;
	for(int i=30;i>=0;i--){
		ll ch=x>>i&1;
		if(Trie[p][!ch]){
			ans|=(1<<i);
			p=Trie[p][!ch];
		}
		else{
			p=Trie[p][ch];
		}
	}
	return ans;
}

Finally

精简版总结

例题还可能会补充。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值