ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前缀树实现思路和例题

2021-10-06 12:04:09  阅读:129  来源: 互联网

标签:node word 前缀 int pass 字符串 path 思路 例题


在这里插入图片描述在这里插入图片描述
在这里插入图片描述
前缀树:每次加字符都从头结点开始加,看有没有通向该字符的路有就复用,没有就新建。
e(end):到该字符为止,该字符串被加入几次。例如:问“bk”字符串被加入几次,发现k处的e=0,则说明一次都没被加入过。
p(pass):经过该字符有几次。例如:问以”ab“开头的字符串有几个,发现b的p=3,所以有3个。

头节点即代表有多少个以空“”开头的字符串,也代表你总共加入多少个字符串

数组(例如:26个字母)
在这里插入图片描述hash表
在这里插入图片描述
插入字符串构建前缀树
在这里插入图片描述
在这里插入图片描述
在前缀树查找字符串出现几次
在这里插入图片描述提前没路
在这里插入图片描述查找有多少个以某字符串开头的字符串
在这里插入图片描述
删除

在这里插入图片描述
你如果想删abc,是只删一次的。即沿途p–,最后一个e–
在这里插入图片描述
在沿途p–的时候减成0了,怎么办?
在这里插入图片描述删除时d的p减为0,将d下面的结点置为空,释放结点

先判断这个word之前加入过没有
在这里插入图片描述下一个节点p减后=0,将其下结点置空

题解

在这里插入图片描述
在这里插入图片描述
代码:

import java.util.*;


public class Solution {
    

        public class TrieTreeNode{
        public int pass;
        public int end;
        
        public TrieTreeNode[] nexts;//接下来的有26条路

        //构造方法
        public TrieTreeNode() {
            pass = 0;
            end = 0;
            nexts = new TrieTreeNode[26];
            }
        }
        
         private TrieTreeNode root=new TrieTreeNode();//根节点
     
        
         //插入方法
    public void insert(String word) {
        if (word == null) return;
        //先将字符串转为字符数组
        char[] chars = word.toCharArray();
        //从根节点开始遍历,沿途pass++
        TrieTreeNode node = root;
        node.pass++;
        int path = 0;
        for (int i = 0; i < chars.length; i++) {
            //获得要选择的那条路
            path = chars[i] - 'a';
            //如果路不存在就创建
            if (node.nexts[path] == null) {
                node.nexts[path] = new TrieTreeNode();
            }
            //路存在,就将当前节点下移,沿途pass++
            node = node.nexts[path];
            node.pass++;


        }
        //到字符串最后end++
        node.end++;
    }
    
     //删除
    public void delete(String word){
        if (word==null) return;
        //先查找一下看该字符串是否存在,存在再删除
        int searchNumbers = search(word);
        if(searchNumbers==0) return;

        char[] chars = word.toCharArray();
        //从根节点开始
        TrieTreeNode node=root;
        //根节点的pass--
        node.pass--;
        int path=0;
        for (int i = 0; i <chars.length ; i++) {
            path=chars[i]-'a';
            if(--node.nexts[path].pass==0){
                //当该节点减1后,pass变成了0(说明该节点之前插入的字符只有一次还是我们要删除的字符串,那下面就不用再查找了,直接将后面字符串置为空)
                node.nexts[path]=null;
                return;
            }

            node=node.nexts[path];//游标继续下移
        }
        node.end--;//最后将该字符串结尾的字符end--

    }
    
     //搜索方法,在前缀树查找字符串出现几次
    public int search(String word) {
        if (word == null) return 0;
        char[] chars = word.toCharArray();
        //从根节点开始遍历
        TrieTreeNode node = root;
        int path = 0;
        for (int i = 0; i < chars.length; i++) {
            path = chars[i] - 'a';
            if (node.nexts[path] == null) {
                return 0;//说明之前没有插入过
            }
            node = node.nexts[path];//之前插入过,结点下移

        }
        return node.end;//到字符串最后一个字符
    }
    
    //查找有多少个以某字符串开头的字符串(和上一个方法唯一的区别就是返回值不一样,一个是end,一个是pass)
    public int prefixNumber(String word){
        if(word==null) return 0;
        char[] chars = word.toCharArray();
        //从根节点开始
        TrieTreeNode node=root;
        int path=0;
        for (int i = 0; i <chars.length ; i++) {
            path=chars[i]-'a';
            if(node.nexts[path]==null){//没路就返回0
                return 0;
            }
            node=node.nexts[path];//有路就继续下移

        }
        return node.pass;
    }


    
    /**
     * 
     * @param operators string字符串二维数组 the ops
     * @return string字符串一维数组
     */
    public String[] trieU (String[][] operators) {
        // write code here
        ArrayList<String> list=new ArrayList();
        //TrieTree trie=new TrieTree();
        for(int i=0;i<operators.length;i++){
              if(Integer.parseInt(operators[i][0])==1){
                 insert(operators[i][1]);
              }else if(Integer.parseInt(operators[i][0])==2){
                  delete(operators[i][1]);
              }else if(Integer.parseInt(operators[i][0])==3){
                  int r=search(operators[i][1]);
                  list.add(r==0?"NO":"YES");
              }else{
                  list.add(prefixNumber(operators[i][1])+"");
              }
        }
       
        return list.toArray(new String[list.size()]);
    }
    
   

}

标签:node,word,前缀,int,pass,字符串,path,思路,例题
来源: https://blog.csdn.net/qq_43430343/article/details/120618270

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有