算法模板-01trie数

trie树

在蓝桥杯中我们需要掌握两种trie树:

字符字典树和01trie树,

其中字符字典树主要用于处理单一字符串面向多个字符串的匹配问题

而01trie树主要用于处理异或最大值的相关问题。

字符字典树

01trie树

01trie树由数组实现,其基本构成如下:

cpp 复制代码
int son[32*N][32];
int idx;
//其中son用于存储每个节点的儿子节点的编号,
//idx用于动态创立儿子节点son的第二位坐标为0表示为左儿子,
//第二位坐标为1表示为右儿子。
void insert(long long x){
	int now=0;
	for (int i=31;i>=0;i--){
		int k=(x>>i)&1;
		if (!son[now][k])
			son[now][k]=++idx;
		now=son[now][k];
	}
}


long long query(long long x){
	int now=0;
	long long res=0;
	for (int i=31;i>=0;i--){
		int k=(x>>i)&1;
		if (son[now][!k]){
			res+=(long long )(1)<<i;
			now=son[now][!k];
		}
		else{
			now=son[now][k];
		}
	}
	return res;
}

代码模板

cpp 复制代码
//不记录每个节点度数的写法
#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;
const int N=1e5+7;
long long a[N];
int son[35*N][35];
int n;
int idx;

void insert(long long x){
	int now=0;
	for (int i=31;i>=0;i--){
		int k=(x>>i)&1;
		if (!son[now][k])
			son[now][k]=++idx;
		now=son[now][k];
	}
}

long long query(long long x){
	int now=0;
	long long res=0;
	for (int i=31;i>=0;i--){
		int k=(x>>i)&1;
		if (son[now][!k]){
			res+=(long long )(1)<<i;
			now=son[now][!k];
		}
		else{
			now=son[now][k];
		}
	}
	return res;
}
long long ans=0;
int main(){
	cin>>n;
	for (int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		insert(a[i]);
	}
	for (int i=1;i<=n;i++){
		ans=max(ans,query(a[i]));
	}
	cout<<ans<<endl;
	return 0;
}
cpp 复制代码
//记录每个节点度数的写法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;

int n;
const int N=1e5+7;
long long a[N];
set<int > f[N];
int idx;
int son[N*35][2];
int degree[N*35];
void build(long long x,int cnt){
	int now=0;
	for (int i=31;i>=0;i--){
		int k=(x>>i)&1;
		if (!son[now][k]){
			son[now][k]=++idx;
		}
		now=son[now][k];
		degree[now]+=cnt;
	}
}

long long query(long long x){
	int now=0;
	long long res=0;
	for (int i=31;i>=0;i--){
		int k=(x>>i)&1;
		if (son[now][!k]&&(degree[son[now][!k]]>0)){
			now=son[now][!k];
			res+=1<<i; 
		}
		else{
			now=son[now][k];
		}
	}
	return res;
}
long long ans;
int main(){
	cin>>n;
	for (int i=0;i<n;i++){
		scanf("%lld",&a[i]);
		build(a[i],1);
	}
	for (int i=0;i<n;i++){
		int x;
		scanf("%d",&x);
		if (x==-1)
			continue;
		f[i].insert(x);
		f[x].insert(i);
	}
	for (int i=0;i<n;i++){
		for (set<int>::iterator j=f[i].begin();j!=f[i].end();j++){
			build(a[*j],-1);
		} 
		long long k=query(a[i]);
		ans=max(ans,k);
		for (set<int>::iterator j=f[i].begin();j!=f[i].end();j++){
			build(a[*j],1);
		}
	}
	cout<<ans<<endl;
	return 0;
}

例题

(1.lgU395507 最大异或对(01Trie))https://www.luogu.com.cn/problem/U395507

该题解答即为上述模板中不记录每个节点度数的写法。

(2.P13874 蓝桥杯 2024 省 Java/Python A 最大异或结点)https://www.luogu.com.cn/problem/P13874

该题解答即为上述模板中记录每个节点度数的写法。

相关推荐
纪念 2295 小时前
C++ 算法(模拟)
开发语言·c++·算法
揽星河..5 小时前
【C语言】函数
c语言·算法
zwc32104320556 小时前
Day 2:图像内存、数据类型与stride
c++·人工智能·opencv·算法·计算机视觉
重生之小比特6 小时前
【算法拾光】模拟|提莫攻击 + N 字形变换
算法·模拟
道尔柯南6 小时前
C++ 内存管理详解:从 malloc/free 到 new/delete
c++·面试
東隅已逝,桑榆非晚6 小时前
AVL数实现
c++·笔记·学习·算法
思想觉悟6 小时前
SEAndroid实战
android·linux·c++
驭渊的小故事7 小时前
LeetCode 算法题解:滑动窗口与数组合并的实战应用
算法·leetcode·职场和发展
.YM.Z7 小时前
优选算法——【双指针算法2】C++实现
开发语言·c++·算法
思想觉悟7 小时前
Aosp开发磨刀石之ADB速查
android·c++