package class06; public class Code01_MaxXOR { // O(N^2) public static int maxXorSubarray1(int[] arr) { if (arr == null || arr.length == 0) { return 0; } // 准备一个前缀异或和数组eor // eor[i] = arr[0...i]的异或结果 int[] eor = new int[arr.length]; eor[0] = arr[0]; // 生成eor数组,eor[i]代表arr[0..i]的异或和 for (int i = 1; i < arr.length; i++) { eor[i] = eor[i - 1] ^ arr[i]; } int max = Integer.MIN_VALUE; for (int j = 0; j < arr.length; j++) { for (int i = 0; i <= j; i++) { // 依次尝试arr[0..j]、arr[1..j]..arr[i..j]..arr[j..j] max = Math.max(max, i == 0 ? eor[j] : eor[j] ^ eor[i - 1]); } } return max; } // 前缀树的Node结构 // nexts[0] -> 0方向的路 // nexts[1] -> 1方向的路 // nexts[0] == null 0方向上没路! // nexts[0] != null 0方向有路,可以跳下一个节点 // nexts[1] == null 1方向上没路! // nexts[1] != null 1方向有路,可以跳下一个节点 public static class Node { public Node[] nexts = new Node[2]; } // 基于本题,定制前缀树的实现 public static class NumTrie { // 头节点 public Node head = new Node(); public void add(int newNum) { Node cur = head; for (int move = 31; move >= 0; move--) { int path = ((newNum >> move) & 1); cur.nexts[path] = cur.nexts[path] == null ? new Node() : cur.nexts[path]; cur = cur.nexts[path]; } } // 该结构之前收集了一票数字,并且建好了前缀树 // num和 谁 ^ 最大的结果(把结果返回) public int maxXor(int num) { Node cur = head; int ans = 0; for (int move = 31; move >= 0; move--) { // 取出num中第move位的状态,path只有两种值0就1,整数 int path = (num >> move) & 1; // 期待遇到的东西 int best = move == 31 ? path : (path ^ 1); // 实际遇到的东西 best = cur.nexts[best] != null ? best : (best ^ 1); // (path ^ best) 当前位位异或完的结果 ans |= (path ^ best) << move; cur = cur.nexts[best]; } return ans; } } // O(N) public static int maxXorSubarray2(int[] arr) { if (arr == null || arr.length == 0) { return 0; } int max = Integer.MIN_VALUE; // 0~i整体异或和 int xor = 0; NumTrie numTrie = new NumTrie(); numTrie.add(0); for (int i = 0; i < arr.length; i++) { xor ^= arr[i]; // 0 ~ i max = Math.max(max, numTrie.maxXor(xor)); numTrie.add(xor); } return max; } // for test public static int[] generateRandomArray(int maxSize, int maxValue) { int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; for (int i = 0; i < arr.length; i++) { arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); } return arr; } // for test public static void printArray(int[] arr) { if (arr == null) { return; } for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } // for test public static void main(String[] args) { int testTime = 500000; int maxSize = 30; int maxValue = 50; boolean succeed = true; for (int i = 0; i < testTime; i++) { int[] arr = generateRandomArray(maxSize, maxValue); int comp = maxXorSubarray1(arr); int res = maxXorSubarray2(arr); if (res != comp) { succeed = false; printArray(arr); System.out.println(res); System.out.println(comp); break; } } System.out.println(succeed ? "Nice!" : "Fucking fucked!"); } }