前缀树:略
前缀树简单实现:(简单的添加和查找,和删除操作)
public static class Node {
public int path;
public int end;
public Node[] next;
public Node() {
path = 0;
end = 0;
next = new Node[26];
}
}
public static class TrieTree {
public Node node;
public TrieTree() {
node = new Node();
}
public void insert(String Word) {
if (Word == null) {
return;
}
Node root = node;
int index = 0;
char[] word = Word.toCharArray();
for (int i = 0; i < word.length; i++) {
index = word[i] - 'a';
if (root.next[index] == null) {
root.next[index] = new Node();
}
root = root.next[index];
root.path++;
}
root.end++;
}
public void deleve(String Word) {
if (Word != null) {
Node root = node;
int index = 0;
char[] word = Word.toCharArray();
for (int i = 0; i < word.length; i++) {
index = word[i] - 'a';
if (root.next[index].path == 1) {
root.next[index] = null;
return;
}
root.next[index].path--;
root = root.next[index];
}
root.end--;
}
}
public int search(String Word) {
if (Word == null) {
return 0;
}
Node root = node;
int index = 0;
char[] word = Word.toCharArray();
for (int i = 0; i < word.length; i++) {
index = word[i] - 'a';
if (root.next[index] == null) {
return 0;
}
root = root.next[index];
}
return root.end;
}
}
其中,删除操作以下部分可简化些:
if (root.next[index].path == 1) {
root.next[index] = null;
return;
}
root.next[index].path--;
简化为:
if (--root.next[index].path == 0) {
root.next[index] = null;
return;
}
前缀树的应用:(给定数组的最大异或和)
思路:
首先,做一个类似“黑盒”的东西,作用:添加和计算(两者最重要的点便是把O(n)的操作缩减到常数级别的,这点在优化上重要);
1.添加:
应用a ^ b = c 则 c ^ a = b, c ^ b = a的规律:
把每一个0~i的异或和用前缀树存储起来,以便查询出最大异或和;
2.计算:
跟添加不同的是多了一个最好情况和验证的情况。
然后就是遍历一遍数组中的每一个,没啥可讲的了!
偏要讲的话,int path = ((res >> j) & 1);这句算得上是亮点吧,嗯
public static class Node {
public Node[] nexts = new Node[2];
}
public static class Heihe {
public Node head = new Node();
public void add(int bra) {
Node cur = head;
for (int i = 31; i >= 0; i--) {
int path = ((bra >> i) & 1);
cur.nexts[path] = cur.nexts[path] == null ? new Node()
: cur.nexts[path];
cur = cur.nexts[path];
}
}
public int maxXor(int res) {
Node cur = head;
int output = 0;
for (int j = 31; j >= 0; j--) {
int path = ((res >> j) & 1);
int best = j == 31 ? path : (path ^ 1);
best = cur.nexts[best] != null ? best : (best ^ 1);
output |= (best ^ path) << j;
cur = cur.nexts[best];
}
return output;
}
}
public static int Max(int[] arr) {
if (arr.length == 0 || arr == null) {
return 0;
}
Heihe box = new Heihe();
int res = 0;
box.add(0);
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
res ^= arr[i];
max = Math.max(max, box.maxXor(res));
box.add(res);
}
return max;
}
public class zzzl_EOR_Max {
public static class Node {
public Node[] nexts = new Node[2];
}
public static class Heihe {
public Node head = new Node();
public void add(int bra) {
Node cur = head;
for (int i = 31; i >= 0; i--) {
int path = ((bra >> i) & 1);
cur.nexts[path] = cur.nexts[path] == null ? new Node()
: cur.nexts[path];
cur = cur.nexts[path];
}
}
public int maxXor(int res) {
Node cur = head;
int output = 0;
for (int j = 31; j >= 0; j--) {
int path = ((res >> j) & 1);
int best = j == 31 ? path : (path ^ 1);
best = cur.nexts[best] != null ? best : (best ^ 1);
output |= (best ^ path) << j;
cur = cur.nexts[best];
}
return output;
}
}
public static int Max(int[] arr) {
if (arr.length == 0 || arr == null) {
return 0;
}
Heihe box = new Heihe();
int res = 0;
box.add(0);
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
res ^= arr[i];
max = Math.max(max, box.maxXor(res));
box.add(res);
}
return max;
}