最大异或对(Trie 字典树)

最大异或对

题目链接
在给定的N个整数A1,A2……AN中选出两个进行xor(异或)运算,得到的结果最大是多少?

输入格式

第一行输入一个整数N。
第二行输入N个整数A1~AN。

输出格式

输出一个整数表示答案。

数据范围

1≤N≤105,
0≤Ai<231.

输入样例:

3
1 2 3

输出样例:

3

算法分析

这题如果要暴力的话就是 至少O(n2) 最多O(31n2)那肯定是不行的,那么就要进行优化,遍历数是无法避免的.而异或是可以进行位运算的,所以我们以位运算来进行优化,要是异或和大,那么位不同的数越多越好.每一位我们用二进制表示,那么就可以转换为字典树的形式,来遍历,这样我们的时间复杂度就可以降到O(31n).

代码实现

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=1e5+5;
int n,a[maxn];
int son[maxn*31][2],idx;
//son[p][u] p代表当前所在树枝,u代表当前所在结点是1还是0;
void insert(int x)
{
	int p=0;
	for(int i=30;i>=0;i--)//从最高位30位进行遍历
	{
		int u=x>>i&1;//当前位数为1的话就是1.
		if(!son[p][u])//如果不存在当前节点,就建立	
			son[p][u]=++idx;
		p=son[p][u];//更新树枝,往下遍历	
	}
}
int quary(int x)
{
	int res=0;	//代表和
	int p=0;
	for(int i=30;i>=0;i--)//从高位遍历
	{
		int u=x>>i&1; //当前位数为1的话就是1.
		if(son[p][!u])//如果有和当前位不同的分支,我们就走该分支保证异或最大.
		{
			p=son[p][!u];//更新分支
			res+=1<<i;//加上当前位所代表的数量(因为只要不相同就是1,不用管数是谁)	
		}
		else	//没有不同的结点就继续往下遍历
			p=son[p][u];	
	}
	return res;
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		insert(a[i]);
	}
	int res=0;
	for(int i=1;i<=n;i++)//寻找最大值
	{
		res=max(res,quary(a[i]));
	}
	cout<<res<<endl;
} 
上一篇:POJ 1451 T9(Trie+思维)


下一篇:ADT: Trie Tree 字典树(附 Java 实现)