Trie

Trie即前缀树,又称为字典树或者单词查找树。Trie典型的应用是搜索引擎系统用于文本词频统计。Trie的优点是利用字符串的公共前缀,来减少查询的时间,最大限度减少无谓的字符串比较,查询效率很高。如图所示:


image.png

上面这个Trie中包含的字符串的集合为:

{"abc","abd","b","ba","cb","cd"}

一个完整的字典树,应该包含的信息如上所示,root节点下每个节点存储着path变量,path变量代表在插入一个节点过程中该路径共经过了多少次;每个节点存储着end变量,end变量代表一个字符串的结尾,只需要这些信息,我们就可以还原出整棵树。
除了对字典树进行添加删除操作外,字典树还可以快速查询某个字符串是否在字典树中,也可以快速查询字典树中是否有以某个前缀为开头的字符串。
字典树结构如下:

public class TrieTree {

    public static class TrieNode{
        public int path;
        public int end;
        public TrieNode[] nexts;

        public TrieNode(){
            path = 0;
            end = 0;
            nexts = new TrieNode[26];
        }
    }

    public static class Trie{
        private TrieNode root;

        public Trie(){
            root = new TrieNode();
        }

        public void insert(String word){
            if(word == null)
                return;

            char[] chars = word.toCharArray();
            TrieNode node = root;
            int index = 0;
            for(int i = 0;i < chars.length;i++){
                index = chars[i] - 'a';
                if(node.nexts[index] == null){
                    node.nexts[index] = new TrieNode();
                }
                node = node.nexts[index];
                node.path++;
            }
            node.end++;
        }

        // search:在字典树中是否存在某个字符串 返回具体的个数,如果不存在返回 0
        public int search(String word){
            if(word == null)
                return 0;

            char[] chars = word.toCharArray();
            TrieNode node = root;
            int index = 0;
            int res = 0;
            for(int i = 0;i < chars.length;i++){
                index = chars[i] - 'a';
                if(node.nexts[index] == null){
                    return 0;
                }
                node = node.nexts[index];
            }
            return node.end;
        }

        // delete
        public void delete(String word){
            if(search(word) > 0){
                char[] chars = word.toCharArray();
                TrieNode node = root;
                int index = 0;
                for(int i = 0;i < chars.length;i++){
                    index = chars[i] - 'a';
                    node = node.nexts[index];
                    if(--node.path == 0){
                        node = null;
                        return;
                    }
                }
                node.end--;
            }
        }
        
        //  在Trie中有多少个以pre为前缀的字符串
        public int prefixNumber(String pre){
            if(pre == null)
                return 0;
            char[] chars = pre.toCharArray();
            TrieNode node = root;
            int index = 0;
            for(int i = 0;i < chars.length;i++){
                index = chars[i] - 'a';
                if(node.nexts[index] == null){
                    return 0;
                }
                node = node.nexts[index];
            }
            return node.path;
        }
    }
}

全部评论

相关推荐

点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务