zoukankan      html  css  js  c++  java
  • 【40讲系列11】字典树

    一、理论

    1. 基本结构

    Trie树,即字典树或单词查找树。典型应用是用于统计和排序大量的字符串(不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

    优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。

    2. 核心思想

    空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

    3. 基本性质

    从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

    每个节点的所有子节点包含的字符都不相同。

    二、典型例题

    ☆☆①:实现一个Trie字典树(LC208)【字节】

    class Trie {
        // 内部类
        private class Node {
            public boolean isWord;
            public Node[] children; // 记录孩子节点
    
            public Node() {
                isWord = false;
                children = new Node[26];
            }
        }
    
        private Node root; // 前缀树的根
    
        /** Initialize your data structure here. */
        public Trie() {
            root = new Node();
        }
        
        /** Inserts a word into the trie. */
        public void insert(String word) {
            Node cur = root;     // 从根出发
            for (char c : word.toCharArray()) {
                if (cur.children[c - 'a'] == null){
                    cur.children[c - 'a'] = new Node();
                }
                cur = cur.children[c - 'a']; // 指向当前节点
            }
            cur.isWord = true; //最后的节点为单词的最后一个单词,is_end设置为true
        }
        
        /** Returns if the word is in the trie. */
        public boolean search(String word) {
            Node cur = root; // 从根出发
            for (char c : word.toCharArray()) {
                if (cur.children[c - 'a'] == null) {
                    return false;
                }
                cur = cur.children[c - 'a'];
            }
            return cur.isWord;
        }
        
        /** Returns if there is any word in the trie that starts with the given prefix. */
        public boolean startsWith(String prefix) {
            Node cur = root; // 从根出发
            for (char c : prefix.toCharArray()) {
                if (cur.children[c - 'a'] == null) {
                    return false;
                }
                cur = cur.children[c - 'a'];
            }
            return true;
        }
    }

    ☆☆☆☆②:二维网格中的单词搜索问题(LC212)

    思路:DFS+字典树。 首先将每个单词都放入Trie中,然后在board[][]中搜索。

    class Solution {
        List<String> res = new ArrayList<>();
    
        public List<String> findWords(char[][] board, String[] words) {
            if (board.length == 0 || words.length == 0) return res;
    
            Trie trie = new Trie();
            for (String word : words){
                trie.insert(word); // 将word存入字典树
            }
            boolean[][] isVisted = new boolean[board.length][board[0].length];
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[0].length; j++) {
                    dfs(board,isVisted,i,j,trie.root);
                }
            }
            return res;
        }
        public void dfs(char[][] board, boolean[][] isVisted, int i, int j, Node cur){
            if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) return;
            if (isVisted[i][j]) return;
    
            char c =board[i][j];
            cur = cur.children[c - 'a'];
            if (cur == null) return;
            if (cur.isWord){
                res.add(cur.val);
                cur.isWord = false;  // 去重操作,也可以使用HashSet
            }
    
            isVisted[i][j] = true;
            dfs(board,isVisted,i - 1,j,cur);
            dfs(board,isVisted,i + 1,j,cur);
            dfs(board,isVisted,i,j - 1,cur);
            dfs(board,isVisted,i,j + 1,cur);
            isVisted[i][j] = false;
        }
    }
    
    /**
     *  字典树
     */
    class Trie {
        public Node root;
        public Trie() {
            root = new Node();
        }
        public void insert(String word){
            Node cur = root;
            for (char c : word.toCharArray()){
                if (cur.children[c - 'a'] == null){
                    cur.children[c - 'a'] = new Node();
                }
                cur = cur.children[c - 'a'];
            }
            cur.isWord = true;
            cur.val = word; // 把单词存起来
        }
    }
    public class Node {
        public String val; // 很关键,用来存单词
        public boolean isWord;
        public Node[] children;
    
        public Node() {
            isWord = false;
            children = new Node[26];  // 单词由小写英文字母组成
        }
    }
  • 相关阅读:
    [java]struts2 模型驱动 2016-05-01 21:40 702人阅读 评论(19) 收藏
    [CS]C#操作word 2016-04-17 18:30 1506人阅读 评论(35) 收藏
    软件设计 2016-04-03 18:21 1012人阅读 评论(26) 收藏
    sqlite数据库文件导入到sqlserver 2016-03-26 21:55 1292人阅读 评论(1) 收藏
    C/S和B/S交互 2016-03-19 11:27 1275人阅读 评论(30) 收藏
    DESede/CBC/PKCS5Padding
    Gson应用:利用map和list来拼装Json消息
    使用Log4j2,打包后提示ERROR StatusLogger Log4j2 could not find a logging implementation.
    Jinkins定时任务设置
    给Fitnesse添加调用多参数fixture的调用方法
  • 原文地址:https://www.cnblogs.com/HuangYJ/p/14024706.html
Copyright © 2011-2022 走看看