题意:给你n个数,然后q次询问,每次询问让你找指定值x与n个数中的哪个数异或后最大。
01字典树的实现可以看成是把一个数的二进制字符化后插入到一颗一般的字典树中
比如在01字典树种插入3时 相当于在字典树中插入00 …..00011(一共32位,这个根据具体问题)
查找最大异或值的时候我们是从最高位 向下贪心查找 贪心策略为:当前查找第k位 二进制数位IDX 如果存在IDX ^ 1的节点 我们就进入这个
节点 否则进入IDX节点 贪心策略的证明: 如果这时我们进入了第K位为IDX 的节点 那么 第k位为IDX ^ 1 的节点组成的数 异或X一定更大
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int val;
node *next[2];
node()
{
val = 0;
memset(next, 0, sizeof(next));
}
};
node *root;
void buildTrie(int x)
{
node *cur = root;
for(int i = 31; i >= 0; i--)
{
int idx = (x>>i)&1;
if(!cur->next[idx])
{
node *tmp = new node;
cur->next[idx] = tmp;
cur = tmp;
}
else
cur = cur->next[idx];
}
cur->val = x;
}
int findTrie(int x)
{
node *cur = root;
for(int i = 31; i >= 0; i--)
{
int idx = (x>>i)&1;
if(cur->next[idx^1])
cur = cur->next[idx^1];
else
cur = cur->next[idx];
}
return cur->val;
}
void deleateTrie(node *cur)
{
for(int i = 0; i < 2; i++)
if(cur->next[i])
deleateTrie(cur->next[i]);
delete cur;
}
int main(void)
{
int t, ca = 1, n, q, x;
cin >> t;
while(t--)
{
root = new node;
scanf("%d %d", &n, &q);
for(int i = 1; i <= n; i++)
scanf("%d", &x), buildTrie(x);
printf("Case #%d:\n", ca++);
while(q--)
{
scanf("%d", &x);
printf("%d\n", findTrie(x));
}
deleateTrie(root);
}
return 0;
}