【Trie tree】| AcWing 143. The largest XOR pair

Title description

Select two of the given N integers A 1 , A 2 … A N to perform the xor (exclusive OR) operation. What is the maximum result obtained?

Input format
Enter an integer N in the first line.

Enter N integers A 1~A N in the second line .

Output format
Output an integer to represent the answer.

data range

1≤N≤105,
0≤Ai<231

Input sample:

3
1 2 3

Sample output:

3

Thinking analysis

0≤A i <2 31 , that is, the maximum value is 2 31 -1, that is, 31 ones, so the maximum binary representation of an integer is 31 bits, that is to say, it can become a binary string with a length of 31 bits, so the difference is The maximum result of the OR operation is 1111……11 (31 1)

According to the nature of XOR, the difference is 1, and the same is 0 , so the two decimal numbers a and b a^b, when each binary digit of a and b selected are different from each other, the largest XOR result will eventually be obtained ( 31 1) .
If this is the case, then we can do this. Every time we search, we will go to the position opposite to the current a i , that is, let the XOR value be the largest. If there is no way to go, then go The same way.

The process of finding XOR pairs:

Finding is a mutual process. Finding b by a is equivalent to finding a by b. So instead of finding a number to match several numbers, it is better to make a number match by several numbers:
first store the first number A 1 Trie tree (initialization) , then A 2 can only match with A 1 in the Trie tree. After the matching is completed, A 2 is added to the Trie tree, and then A 3 can only match with A 1 or A 2 in the Trie tree . Find the results can be the biggest, followed by a 4 ...... and so on, up to a N .

  1. Match the number between A 1 and A x-1 in A x and Trie tree ; ② A x joins the Trie tree. ①②There is no need for the order of the two, because even if A x is inserted into the Trie tree first, the matching result between itself and itself is 0, it has no effect, but it is still recommended to match and then insert.
  2. Should be the normal sequential A X and A . 1 + X to A N number between , i.e. matching A . 1 and the first A 2 to A N between the number of matches, A 2 , and A . 3 to A N number of matches between , But it is not convenient to insert the Trie tree, so reverse thinking is adopted.

The key to the problem:

1. Binary numbers are stored in the Trie tree

Binary numbers have only 0 and 1, so there are only two branches.

Each decimal number uniquely corresponds to a binary number, so in the Trie tree from level 1 to level 31, as long as one branch is different, a completely different number is selected.
In order to get the largest result, we should start from the highest position , and then go to the lower position to find the best solution on the premise of the highest position.

egIf x=(10010) 2 , its maximum XOR should be (01101) 2 , which is all 1s.
If there is (01101) 2 in the trie tree , then the match starts from the high position or the low position, and the match is (01101) 2 ;
but if there is no trie tree, if the largest in the Trie tree is (01000) 2 , The 0th bit is the same as the 2nd bit, and the other bits are different. Starting from the highest bit, you can find (01000) 2 , but if you match from the lowest bit, the lowest 0 must go to the 1 in the Trie tree. This will not match (01000) 2 anyway .

2. Search process

Given a number x, find the largest XOR pair in the Trie tree:
start from the highest bit, and each time we search, we will go to the opposite position to the current a i , that is, let the XOR value be the largest , If there is no way to go, then go the same way.

3. Split an integer into 31-bit binary representation

int x,t;
for (int i=30;i>-1;i--)  t=x>>i&1; 

Start from the highest bit and take one bit at a time.
And here can only take 1 or 0, and can’t take other numbers, so it can’t be written ast=x&(1<<i);

Code

Analyze 2 31 ,
2 10 and 10 3 are approximate, so 2 30 is approximately similar to 10 9 , that is, 1e9, 2 31 is approximately 2e9, less than 3e9, you can use the int type to define a trie two-dimensional array.

#include <iostream>
#define read(x) scanf("%d",&x)

using namespace std;

const int N=1e5+10;
int a[N];
int trie[N*32][2],idx=1; "idx为0的时候存储根节点,已经默认了,下一个结点从1开始"

void insert(int x)
{
    
    
    int p=0; //从根节点0开始插入
    for (int i=30;i>-1;i--) {
    
     "要保证异或结果最大,从最高位开始取,共31位,所以共取30次"
        int t=x>>i&1;  "这是一个处理过程,01串中取出每一位,每种字符串不一样,小写字母串就处理成t=a[i]-'a',映射成列坐标"
        if (!trie[p][t]) trie[p][t]=idx++;
        p=trie[p][t];
    }
}

int find(int x) //找到一个和x异或结果最大的异或对
{
    
    
    int p=0,res=0;
    for (int i=30;i>-1;i--) {
    
    
        int t=x>>i&1;
        if (trie[p][!t]) res+=1<<i,p=trie[p][!t]; "优先考虑走不同分支,使该位的值为1,并加上相应的值:1<<i"
        else p=trie[p][t];  "如果没有不同的分支,只能走相同的分支,那么该位就是0,不用加"
    }
    return res; //最后返回异或的结果
}

int main()
{
    
    
    int n;
    read(n);
    for (int i=0;i<n;i++) read(a[i]);
    insert(a[0]);
    int res=-1; "异或的结果必大于等于0"
    for (int i=1;i<n;i++) {
    
    
        res=max(res,find(a[i]));  //每次取最大的结果
        insert(a[i]);   "先比较,再插入Trie树"
    }
    printf("%d",res);
    
    return 0;
}

Different thinking of find function, flexible use of bit operation:

int find(int x)
{
    
    
    int p=0,res=0;
    for  (int i=30;i>-1;i--) {
    
    
        int t=x>>i&1;
        if (trie[p][!t]) res=res*2+1,p=trie[p][!t];
        else res=res*2,p=trie[p][t];
    }
    return res;
}

In addition to returning the largest XOR result, it can also return the number XORed with x:
So,res=max(res,a[i]^find(a[i]));

int find(int x)
{
    
    
    int p=0,y=0;
    for  (int i=30;i>-1;i--) {
    
    
        int t=x>>i&1;
        if (trie[p][!t]) y=y*2+!t,p=trie[p][!t];
        else y=y*2+t,p=trie[p][t];
    }
    return y;
}
int find(int x)
{
    
    
    int p=0,y=0;
    for  (int i=30;i>-1;i--) {
    
    
        int t=x>>i&1;
        if (trie[p][!t]) y+=!t<<i,p=trie[p][!t];
        else y+=t<<i,p=trie[p][t];
    }
    return y;
}

Guess you like

Origin blog.csdn.net/HangHug_L/article/details/114188474