算法之前缀树(Java)

前缀树:略

前缀树简单实现:(简单的添加和查找,和删除操作)

	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;


	}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值