前缀树题目


词典中最长的单词


在这里插入图片描述
在这里插入图片描述


思路: dfs+前缀树,在前缀树上做dfs,出口是某节点的end值为0,沿途节点的end值都大于0


class Solution {
   public String ans="";//    这个居然不能声明成static类型!!!
    public class TrieNode{
        public int pass;
        public int end;
        public TrieNode[] nexts;
        public TrieNode(int p,int e){
            pass=p;
            end=e;
        }
        public TrieNode(){
            nexts=new TrieNode[26];
        }
    }
    public class Trie{//前缀树
        public TrieNode root;
        public Trie(){
            root=new TrieNode();
        }
        public void add(String s){
            if(s==""||s==null)return;
            TrieNode cur=root;
            cur.pass++;
            for(int i=0;i<s.length();++i){
                if(cur.nexts[s.charAt(i)-'a']==null){
                    cur.nexts[s.charAt(i)-'a']=new TrieNode();
                }
                cur.nexts[s.charAt(i)-'a'].pass++;
                cur=cur.nexts[s.charAt(i)-'a'];
            }
            cur.end++;
        }
    }
    public void dfs(TrieNode root,TrieNode x,String path){
    	//System.out.println(path);
        if(ans.equals(""))ans=path;
        else if(ans.length()<path.length()){
            ans=path;
        }
        else if(ans.length()==path.length()){
            ans=(ans.compareTo(path)<=0?ans:path);
        }
         

        for(int i=0;i<26;++i){
            if(x.nexts[i]!=null&&x.nexts[i].end>0){
                dfs(root,x.nexts[i],path+(char)('a'+i));
            }
        }
        
    }
    public  String longestWord(String[] words) {
        Trie trie=new Trie();
        for(String s:words){
            trie.add(s);
        }
        dfs(trie.root,trie.root,"");
        return ans;
    }
}

在这里插入图片描述


前缀树结构实现

在这里插入图片描述

import java.util.*;


public class Solution {
    /**
     * 
     * @param operators string字符串二维数组 the ops
     * @return string字符串一维数组
     */
    public static class TrieNode{
		public int p;
		public int e;
		public HashMap<Character,TrieNode>nextNodes;
		public TrieNode() {
			p=0;
			e=0;
			nextNodes=new HashMap<>();
		}
	}
	public static class TrieTree{//前缀树结构
		public TrieNode root;
		//添加字符串,可重复添加
		public TrieTree() {
			root=new TrieNode();
		}
		public void insert(String word) {
			if(word==null) {
				root.p++;
				return;
			}
			TrieNode cur=root;
			cur.p++;
			char[] chs=word.toCharArray();
			for(int i=0;i<chs.length;++i) {
				if(!cur.nextNodes.containsKey(chs[i])) {
					cur.nextNodes.put(chs[i], new TrieNode());
				}
				cur=cur.nextNodes.get(chs[i]);
				cur.p++;
			}
			cur.e++;
			
		}
		//查询word在字典树中出现过几次(完整的出现过,前缀式不算)
		public int search(String word) {
			if(word==null) {
				return root.p;
			}
			TrieNode cur=root;
			char[] chs=word.toCharArray();
			for(int i=0;i<chs.length;++i) {
				if(!cur.nextNodes.containsKey(chs[i])) {
					return 0;
				}
				cur=cur.nextNodes.get(chs[i]);
			}
			return cur.e;
		}
		//返回以字符串pre作为前缀的单词数量
		public int prefixNumber(String pre) {
			if(pre==null)return root.p;
			TrieNode cur=root;
			char[] chs=pre.toCharArray();
			for(int i=0;i<chs.length;++i) {
				if(!cur.nextNodes.containsKey(chs[i])) {
					return 0;
				}
				cur=cur.nextNodes.get(chs[i]);
			}
			return cur.p;
		}
		//删除word,如果word添加过多次,仅删除一次
		public void delete(String word) {
			if(search(word)==0) {
				return;
			}
			TrieNode cur=root;
			char[] chs=word.toCharArray();
			for(int i=0;i<chs.length;++i) {
				if(cur.nextNodes.get(chs[i]).p==0) {
					cur.nextNodes.put(chs[i], null);
				}
				cur.p--;
				cur=cur.nextNodes.get(chs[i]);
			}
			cur.e--;
			
		}
		
	}
    public String[] trieU (String[][] operators) {
        ArrayList<String>list=new ArrayList<>();
        TrieTree root=new TrieTree();
        for(int i=0;i<operators.length;++i){
            switch(operators[i][0]){
                case "1":{
                    root.insert(operators[i][1]);
                    break;
                }
                case "2":{
                    root.delete(operators[i][1]);
                    break;
                }
                case "3":{
                    if(root.search(operators[i][1])!=0)list.add("YES");
                    else list.add("NO");
                    break;
                }
                case "4":{
                    list.add(root.prefixNumber(operators[i][1])+"");
                    break;
                }
                  
            }
        }
        String[] ans=new String[list.size()];
        int k=0;
        for(String s:list){
            ans[k++]=s;
        }
        return ans;
    }
}

在这里插入图片描述



最大子数组异或和

在这里插入图片描述
在这里插入图片描述

import java.util.Scanner;

public class Main {
	public static class Node{
		public Node[] nexts;
		public Node() {
			nexts=new Node[2];
		}
	}
	public static class PreTree{//前缀树结构
		public Node head=new Node();
		public int maxEor(int[] arr) {
			int max=Integer.MIN_VALUE;
			int res=0;
			add(0);
			for(int i=0;i<arr.length;++i) {
				res^=arr[i];//res:  0~i异或和
				//[k..i]=[0..i]^[0..k-1]
				max=Math.max(max, getMaxSubArray(res));
//				System.out.println(getMaxSubArray(res));
				add(res);
			}
			
			return max;
		}
		public void add(int x) {
			Node cur=head;
			for(int move=31;move>=0;--move) {
				int path=(x>>move)&1;
				if(cur.nexts[path]==null) {
					cur.nexts[path]=new Node();
				}
				cur=cur.nexts[path];
			}
		}
		public int getMaxSubArray(int res) {
			Node cur=head;
			int ans=0;
			for(int move=31;move>=0;--move) {
				int path=(res>>move)&1;
				int best=(move==31?path:(path^1));
				best=(cur.nexts[best]==null?(best^1):best);
				ans|=((best^path)<<move);
				cur=cur.nexts[best];
			}
			return ans;
			
		}
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int[] arr=new int[n];
		for(int i=0;i<n;++i) {
			arr[i]=scan.nextInt();
		}
		PreTree pt=new PreTree();
		System.out.println(pt.maxEor(arr));
	}

}

在这里插入图片描述





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值