142 子数组的最大异或和
Table of Contents

ac

数组异或和的定义:把数组中所有的数异或起来得到的值。给定一个整型数组arr,其中可能有正、有负,有零,求其中子数组的最大异或和。

异或性质

1、交换律

2、结合律(即(a^b)^c == a^(b^c)

3、对于任何数x,都有x^x=0x^0=x

4、自反性 A XOR B XOR B = A xor 0 = A

如果: E1 ^ E2 = E3
则: E1 ^ E3 = E2, E2 ^ E3 = E1

eg:

  0101   0101    1010
^ 1010   1111    1111
  1111   1010    0101

【0-i-1的异或和】 ^ 【0-j-1的异或和】 = 【j到i-1的异或和】

前缀+利用异或性质

0-0
0-1
0-2
0-3
0-i-1

【0 ... x】^ 【0 ... i】 = 【x+1 ... i】

即以i结尾的最大异或和就是0到某一位置x的异或结果和0-i异或结果最大,举个例子,假设x是3,0-3的异或结果和0-i进行异或得到的结果最大,那么就说明4-i的异或结果是最大的

eg:

0异或任何数都是这个数
0-1 ^ 0-3 = 2-3
0-1 ^ 0-2 = 2
0-0 ^ 0-3 = 1-3

所以问题最后转化为:求前缀异或和中每两个数的异或和最大的,初始需要前缀树中有个0

int整数,最高位是符号位(0为正数,1为负数),对于异或操作
只要符号位相同,后面31位相异的越多,那么最后异或操作得到的值就越大

ac

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

class Trie{

    Node root = new Node();

    class Node{
        Node[] next;
        public Node() {
            next = new Node[2];
            for(int i=0;i<2;i++){
                next[i] = null;
            }
        }
    }

    // 将一个数加到字典树里面
    void add(int num){
        Node cur = root;
        for(int move = 31;move >= 0;move--) {
            int bit = ((num >> move) & 1);//每一位上的数字(0,1)
            if(cur.next[bit] == null){
                cur.next[bit] = new Node();
            }
            cur = cur.next[bit];
        }
    }

    // 判断num与字典树里面的所有值进行异或能得到的最大值
    int getMaxXOR(int num){
        Node cur = root;
        int res = 0;
        for(int move = 31;move >= 0;move--) {
            int bit = (num >> move) & 1;//提取每一位
            int bestBit; // 选择可能的最大树分支进行异或,符号位选择跟符号位一样的,非符号位选择跟当前不一样的
            if(move == 31){ // 符号位
                bestBit = bit;
            }else { // 非符号位
                bestBit = 1 ^ bit;
            }
            int realbit = bestBit; // 实际选择的可能没有, 那别无选择
            if(cur.next[bestBit] == null){
                realbit = bestBit ^ 1;
            }
            res = res | (bit ^ realbit) << move; // 设置res的每一位
            cur = cur.next[realbit]; //继续往下走
        }
        return res;
    }
}


public class Main {
    public static Scanner sc = new Scanner(System.in);

    public static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    public static long mod = (long)Math.pow(2,29);

    public static void main(String[] args) throws Exception {
        int n = sc.nextInt();
        int[] arr = new int[n];
        int[] preFix = new int[n];
        for(int i=0;i<n;i++){
            arr[i] = sc.nextInt();
            if(i == 0) {
                preFix[i] = arr[i];
            }else {
                preFix[i] = preFix[i-1] ^ arr[i];
            }
        }
        int result = Integer.MIN_VALUE;
        Trie trie = new Trie();
        trie.add(0);
        for(int i=0;i<n;i++){
            result = Math.max(result, trie.getMaxXOR(preFix[i]));
            trie.add(preFix[i]);
        }
        System.out.println(result);
    }


}
/*
4
3 -28 -29 2

7

{-28,-29}这个子数组的异或和为7,是所有子数组中最大的
*/