前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >字典树收集(初步读写锁实现线程安全,待续)

字典树收集(初步读写锁实现线程安全,待续)

作者头像
算法之名
发布2019-08-20 17:38:44
4540
发布2019-08-20 17:38:44
举报
文章被收录于专栏:算法之名

将500W个单词放进一个数据结构进行存储,然后进行快速比对,判断一个单词是不是这个500W单词之中的;来了一个单词前缀,给出500w个单词中有多少个单词是该前缀.

1、这个需求首先需要设计好数据结构,要求快速判断一个单词是否在这500W之中,挨个遍历肯定不是好办法,即便你把他们放在一个数组或者链表里,用多线程分段查找,最好是几次查找就可以知道结果。

我们把所有单词的前缀作为上层,剩下的字符逐级加入到树的下层结构中,并记录树的上层节点的子节点数。这样我们只要判断新单词跟树的上层节点的前缀比对,那么其他不匹配的节点就无需继续遍历,只需要在该节点往下查找后续的字符比对,他的时间复杂度可能就很低了,只需要几次比对就能判断出是否包含该新单词。整个数据结构可以书写如下。

代码语言:javascript
复制
public class DictionaryTree {

    // 字典树的节点
    private class Node {
        // 是否是单词
        private boolean isWord;
        // 单词计数
        private int count;
        // 字串
        private String str;
        // 子节点
        private Map<String, Node> childs;
        // 父节点
        private Node parent;

        public Node() {
            childs = new HashMap<String, Node>();
        }

        public Node(boolean isWord, int count, String str) {
            this();
            this.isWord = isWord;
            this.count = count;
            this.str = str;
        }

        public void addChild(String key, Node node) {
            childs.put(key, node);
            node.parent = this;
        }

        public void removeChild(String key) {
            childs.remove(key);
        }

        public String toString() {
            return "str : " + str + ", isWord : " + isWord + ", count : " + count;
        }
    }

    // 字典树根节点
    private Node root;

    public DictionaryTree() {
        // 初始化root
        root = new Node();
    }

    // 添加字串
    private void addStr(String word, Node node) {

        // 计数
        node.count++;

        String str = node.str;
        if (null != str) {

            // 寻找公共前缀
            String commonPrefix = "";
            for (int i = 0; i < word.length(); i++) {
                if (str.length() > i && word.charAt(i) == str.charAt(i)) {
                    commonPrefix += word.charAt(i);
                } else {
                    break;
                }
            }

            // 找到公共前缀
            if (commonPrefix.length() > 0) {
                if (commonPrefix.length() == str.length() && commonPrefix.length() == word.length()) {
                    // 与之前的词重复
                } else if (commonPrefix.length() == str.length() && commonPrefix.length() < word.length()) {
                    // 剩余的串
                    String wordLeft = word.substring(commonPrefix.length());
                    // 剩余的串去子节点中继续找
                    searchChild(wordLeft, node);
                } else if (commonPrefix.length() < str.length()) {
                    // 节点裂变
                    Node splitNode = new Node(true, node.count, commonPrefix);
                    // 处理裂变节点的父关系
                    splitNode.parent = node.parent;
                    splitNode.parent.addChild(commonPrefix, splitNode);
                    node.parent.removeChild(node.str);
                    node.count--;
                    // 节点裂变后的剩余字串
                    String strLeft = str.substring(commonPrefix.length());
                    node.str = strLeft;
                    splitNode.addChild(strLeft, node);
                    // 单词裂变后的剩余字串
                    if (commonPrefix.length() < word.length()) {
                        splitNode.isWord = false;
                        String wordLeft = word.substring(commonPrefix.length());
                        Node leftNode = new Node(true, 1, wordLeft);
                        splitNode.addChild(wordLeft, leftNode);
                    }
                }
            } else {
                // 没有共同前缀,直接添加节点
                Node newNode = new Node(true, 1, word);
                node.addChild(word, newNode);
            }
        } else {
            // 根结点
            if (node.childs.size() > 0) {
                searchChild(word, node);
            } else {
                Node newNode = new Node(true, 1, word);
                node.addChild(word, newNode);
            }
        }
    }

    // 在子节点中添加字串
    public void searchChild(String wordLeft, Node node) {
        boolean isFind = false;
        if (node.childs.size() > 0) {
            // 遍历孩子
            for (String childKey : node.childs.keySet()) {
                Node childNode = node.childs.get(childKey);
                // 首字母相同,则在该子节点继续添加字串
                if (wordLeft.charAt(0) == childNode.str.charAt(0)) {
                    isFind = true;
                    addStr(wordLeft, childNode);
                    break;
                }
            }
        }
        // 没有首字母相同的孩子,则将其变为子节点
        if (!isFind) {
            Node newNode = new Node(true, 1, wordLeft);
            node.addChild(wordLeft, newNode);
        }
    }

    // 添加单词
    public void add(String word) {
        addStr(word, root);
    }

    // 在节点中查找字串
    private boolean findStr(String word, Node node) {
        boolean isMatch = true;
        String wordLeft = word;
        String str = node.str;
        if (null != str) {
            // 字串与单词不匹配
            if (word.indexOf(str) != 0) {
                isMatch = false;
            } else {
                // 匹配,则计算剩余单词(从匹配的后一位到最后一位)
                wordLeft = word.substring(str.length());
            }
        }
        // 如果匹配
        if (isMatch) {
            // 如果还有剩余单词长度
            if (wordLeft.length() > 0) {
                if (node.childs.size() > 0) {
                    // 遍历孩子继续找
                    for (String key : node.childs.keySet()) {
                        Node childNode = node.childs.get(key);
                        //递归
                        boolean isChildFind = findStr(wordLeft, childNode);
                        if (isChildFind) {
                            return true;
                        }
                    }
                }else {
                    //如果没有子节点了,返回false
                    return false;
                }
            } else {
                // 没有剩余单词长度,说明已经匹配完毕,直接返回节点是否为单词,匹配到即便符合前缀,也不能算单词
                return node.isWord;
            }
        }
        return false;
    }

    // 查找单词
    public boolean find(String word) {
        return findStr(word, root);
    }

    // 统计子节点字串单词数
    private int countChildStr(String prefix, Node node) {
        // 遍历孩子
        for (String key : node.childs.keySet()) {
            Node childNode = node.childs.get(key);
            // 匹配子节点
            int childCount = countStr(prefix, childNode);
            if (childCount != 0) {
                return childCount;
            }
        }
        return 0;
    }

    // 统计字串单词数
    private int countStr(String prefix, Node node) {
        String str = node.str;
        // 非根结点
        if (null != str) {
            // 前缀与字串不匹配
            if (prefix.indexOf(str) != 0 && str.indexOf(prefix) != 0) {
                return 0;
                // 前缀匹配字串,且前缀较短
            } else if (str.indexOf(prefix) == 0) {
                // 找到目标节点,返回单词数
                return node.count;
                // 前缀匹配字串,且字串较短
            } else if (prefix.indexOf(str) == 0) {
                // 剩余字串继续匹配子节点
                String prefixLeft = prefix.substring(str.length());
                if (prefixLeft.length() > 0) {
                    return countChildStr(prefixLeft, node);
                }
            }
        } else {
            // 根结点,直接找其子孙
            return countChildStr(prefix, node);
        }
        return 0;
    }

    // 统计前缀单词数
    public int count(String prefix) {
        // 处理特殊情况
        if (null == prefix || prefix.trim().isEmpty()) {
            return root.count;
        }
        // 从根结点往下匹配
        return countStr(prefix, root);
    }

    // 打印节点
    private void printNode(Node node, int layer) {
        // 层级递进
        for (int i = 0; i < layer; i++) {
            System.out.print("    ");
        }
        // 打印
        System.out.println(node);
        // 递归打印子节点
        for (String str : node.childs.keySet()) {
            Node child = node.childs.get(str);
            printNode(child, layer + 1);
        }
    }

    // 打印字典树
    public void print() {
        printNode(root, 0);
    }
}

我们可以先看findStr()方法,主要是递归查找,也就是递归进去几个节点的事情,就OK了.

代码语言:javascript
复制
// 在节点中查找字串
private boolean findStr(String word, Node node) {
    boolean isMatch = true;
    String wordLeft = word;
    String str = node.str;
    if (null != str) {
        // 字串与单词不匹配
        if (word.indexOf(str) != 0) {
            isMatch = false;
        } else {
            // 匹配,则计算剩余单词(从匹配的后一位到最后一位)
            wordLeft = word.substring(str.length());
        }
    }
    // 如果匹配
    if (isMatch) {
        // 如果还有剩余单词长度
        if (wordLeft.length() > 0) {
            if (node.childs.size() > 0) {
                // 遍历孩子继续找
                for (String key : node.childs.keySet()) {
                    Node childNode = node.childs.get(key);
                    //递归
                    boolean isChildFind = findStr(wordLeft, childNode);
                    if (isChildFind) {
                        return true;
                    }
                }
            }else {
                //如果没有子节点了,返回false
                return false;
            }
        } else {
            // 没有剩余单词长度,说明已经匹配完毕,直接返回节点是否为单词,匹配到即便符合前缀,也不能算单词
            return node.isWord;
        }
    }
    return false;
}

// 查找单词
public boolean find(String word) {
    return findStr(word, root);
}

第二个需求,来了一个单词前缀,给出500w个单词中有多少个单词是该前缀.

我们来看一下countStr()和countChildStr()两个方法的互相调用,其实就是我只要找到完全匹配子节点的数量就可以得到结果.他的时间复杂度也是非常的低.不需要一个个的去到叶节点去累加,因为上层节点已经有他的全部单词节点节点的数量.(上层节点也可能是一个单词,并非只是叶节点)

代码语言:javascript
复制
// 统计子节点字串单词数
private int countChildStr(String prefix, Node node) {
    // 遍历孩子
    for (String key : node.childs.keySet()) {
        Node childNode = node.childs.get(key);
        // 匹配子节点
        int childCount = countStr(prefix, childNode);
        if (childCount != 0) {
            return childCount;
        }
    }
    return 0;
}

// 统计字串单词数
private int countStr(String prefix, Node node) {
    String str = node.str;
    // 非根结点
    if (null != str) {
        // 前缀与字串不匹配
        if (prefix.indexOf(str) != 0 && str.indexOf(prefix) != 0) {
            return 0;
            // 前缀匹配字串,且前缀较短
        } else if (str.indexOf(prefix) == 0) {
            // 找到目标节点,返回单词数
            return node.count;
            // 前缀匹配字串,且字串较短
        } else if (prefix.indexOf(str) == 0) {
            // 剩余字串继续匹配子节点
            String prefixLeft = prefix.substring(str.length());
            if (prefixLeft.length() > 0) {
                return countChildStr(prefixLeft, node);
            }
        }
    } else {
        // 根结点,直接找其子孙
        return countChildStr(prefix, node);
    }
    return 0;
}

// 统计前缀单词数
public int count(String prefix) {
    // 处理特殊情况
    if (null == prefix || prefix.trim().isEmpty()) {
        return root.count;
    }
    // 从根结点往下匹配
    return countStr(prefix, root);
}

添加单词也是非常有意思的,来看这么几个方法.当新增加的单词跟已存在的节点单词有相同的前缀时,就要分裂出一个新的前缀节点,并且把该节点本身以及新增加的单词的后续的字符变成两个下一级节点,如果没有就要新增加一个全新的节点.如果已经有前缀可以匹配了,就要匹配下一层的前缀,其他同之前.

代码语言:javascript
复制
// 添加字串
private void addStr(String word, Node node) {

    // 计数
    node.count++;

    String str = node.str;
    if (null != str) {

        // 寻找公共前缀
        String commonPrefix = "";
        for (int i = 0; i < word.length(); i++) {
            if (str.length() > i && word.charAt(i) == str.charAt(i)) {
                commonPrefix += word.charAt(i);
            } else {
                break;
            }
        }

        // 找到公共前缀
        if (commonPrefix.length() > 0) {
            if (commonPrefix.length() == str.length() && commonPrefix.length() == word.length()) {
                // 与之前的词重复
            } else if (commonPrefix.length() == str.length() && commonPrefix.length() < word.length()) {
                // 剩余的串
                String wordLeft = word.substring(commonPrefix.length());
                // 剩余的串去子节点中继续找
                searchChild(wordLeft, node);
            } else if (commonPrefix.length() < str.length()) {
                // 节点裂变
                Node splitNode = new Node(true, node.count, commonPrefix);
                // 处理裂变节点的父关系
                splitNode.parent = node.parent;
                splitNode.parent.addChild(commonPrefix, splitNode);
                node.parent.removeChild(node.str);
                node.count--;
                // 节点裂变后的剩余字串
                String strLeft = str.substring(commonPrefix.length());
                node.str = strLeft;
                splitNode.addChild(strLeft, node);
                // 单词裂变后的剩余字串
                if (commonPrefix.length() < word.length()) {
                    splitNode.isWord = false;
                    String wordLeft = word.substring(commonPrefix.length());
                    Node leftNode = new Node(true, 1, wordLeft);
                    splitNode.addChild(wordLeft, leftNode);
                }
            }
        } else {
            // 没有共同前缀,直接添加节点
            Node newNode = new Node(true, 1, word);
            node.addChild(word, newNode);
        }
    } else {
        // 根结点
        if (node.childs.size() > 0) {
            searchChild(word, node);
        } else {
            Node newNode = new Node(true, 1, word);
            node.addChild(word, newNode);
        }
    }
}

// 在子节点中添加字串
public void searchChild(String wordLeft, Node node) {
    boolean isFind = false;
    if (node.childs.size() > 0) {
        // 遍历孩子
        for (String childKey : node.childs.keySet()) {
            Node childNode = node.childs.get(childKey);
            // 首字母相同,则在该子节点继续添加字串
            if (wordLeft.charAt(0) == childNode.str.charAt(0)) {
                isFind = true;
                addStr(wordLeft, childNode);
                break;
            }
        }
    }
    // 没有首字母相同的孩子,则将其变为子节点
    if (!isFind) {
        Node newNode = new Node(true, 1, wordLeft);
        node.addChild(wordLeft, newNode);
    }
}

// 添加单词
public void add(String word) {
    addStr(word, root);
}

代码语言:javascript
复制
public void addChild(String key, Node node) {
    childs.put(key, node);
    node.parent = this;
}

然后我们来一个main()方法进行测试,当然没有加500W个单词那么多,但结果是一样,有兴趣你可以加500W个单词进去

代码语言:javascript
复制
public static void main(String[] args) {

    DictionaryTree dt = new DictionaryTree();

    dt.add("interest");
    dt.add("interesting");
    dt.add("interested");
    dt.add("inside");
    dt.add("insert");
    dt.add("apple");
    dt.add("inter");
    dt.add("interesting");
    dt.add("aha");
    dt.add("fuck");
    dt.add("finish");
    dt.add("fish");

    dt.print();

    boolean isFind = dt.find("a");
    System.out.println("find a : " + isFind);

    isFind = dt.find("aha");
    System.out.println("find aha : " + isFind);

    int count = dt.count("inter");
    System.out.println("count prefix inter : " + count);

}

运行结果:

str : null, isWord : false, count : 12 str : a, isWord : false, count : 2 str : ha, isWord : true, count : 1 str : pple, isWord : true, count : 1 str : in, isWord : false, count : 7 str : ter, isWord : true, count : 5 str : est, isWord : true, count : 4 str : ing, isWord : true, count : 2 str : ed, isWord : true, count : 1 str : s, isWord : false, count : 2 str : ert, isWord : true, count : 1 str : ide, isWord : true, count : 1 str : f, isWord : false, count : 3 str : i, isWord : false, count : 2 str : nish, isWord : true, count : 1 str : sh, isWord : true, count : 1 str : uck, isWord : true, count : 1 find a : false find aha : true count prefix inter : 5

实现线程安全性(读写锁实现,初步)

代码语言:javascript
复制
package com.guanjian;

/**
 * Created by Administrator on 2018/10/21.
 */
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class DictionaryTree {
    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private Lock readLock = reentrantReadWriteLock.readLock();
    private Lock writeLock = reentrantReadWriteLock.writeLock();
    // 字典树的节点
    private class Node {
        // 是否是单词
        private boolean isWord;
        // 单词计数
        private int count;
        // 字串
        private String str;
        // 子节点
        private Map<String, Node> childs;
        // 父节点
        private Node parent;

        public Node() {
            childs = new HashMap<String, Node>();
        }

        public Node(boolean isWord, int count, String str) {
            this();
            this.isWord = isWord;
            this.count = count;
            this.str = str;
        }

        public void addChild(String key, Node node) {
            childs.put(key, node);
            node.parent = this;
        }

        public void removeChild(String key) {
            childs.remove(key);
        }

        public String toString() {
            return "str : " + str + ", isWord : " + isWord + ", count : " + count;
        }
    }

    // 字典树根节点
    private Node root;

    public DictionaryTree() {
        // 初始化root
        root = new Node();
    }

    // 添加字串
    private void addStr(String word, Node node) {

        // 计数
        node.count++;

        String str = node.str;
        if (null != str) {

            // 寻找公共前缀
            String commonPrefix = "";
            for (int i = 0; i < word.length(); i++) {
                if (str.length() > i && word.charAt(i) == str.charAt(i)) {
                    commonPrefix += word.charAt(i);
                } else {
                    break;
                }
            }

            // 找到公共前缀
            if (commonPrefix.length() > 0) {
                if (commonPrefix.length() == str.length() && commonPrefix.length() == word.length()) {
                    // 与之前的词重复
                } else if (commonPrefix.length() == str.length() && commonPrefix.length() < word.length()) {
                    // 剩余的串
                    String wordLeft = word.substring(commonPrefix.length());
                    // 剩余的串去子节点中继续找
                    searchChild(wordLeft, node);
                } else if (commonPrefix.length() < str.length()) {
                    // 节点裂变
                    Node splitNode = new Node(true, node.count, commonPrefix);
                    // 处理裂变节点的父关系
                    splitNode.parent = node.parent;
                    splitNode.parent.addChild(commonPrefix, splitNode);
                    node.parent.removeChild(node.str);
                    node.count--;
                    // 节点裂变后的剩余字串
                    String strLeft = str.substring(commonPrefix.length());
                    node.str = strLeft;
                    splitNode.addChild(strLeft, node);
                    // 单词裂变后的剩余字串
                    if (commonPrefix.length() < word.length()) {
                        splitNode.isWord = false;
                        String wordLeft = word.substring(commonPrefix.length());
                        Node leftNode = new Node(true, 1, wordLeft);
                        splitNode.addChild(wordLeft, leftNode);
                    }
                }
            } else {
                // 没有共同前缀,直接添加节点
                Node newNode = new Node(true, 1, word);
                node.addChild(word, newNode);
            }
        } else {
            // 根结点
            if (node.childs.size() > 0) {
                searchChild(word, node);
            } else {
                Node newNode = new Node(true, 1, word);
                node.addChild(word, newNode);
            }
        }
    }

    // 在子节点中添加字串
    public void searchChild(String wordLeft, Node node) {
        boolean isFind = false;
        if (node.childs.size() > 0) {
            // 遍历孩子
            for (String childKey : node.childs.keySet()) {
                Node childNode = node.childs.get(childKey);
                // 首字母相同,则在该子节点继续添加字串
                if (wordLeft.charAt(0) == childNode.str.charAt(0)) {
                    isFind = true;
                    addStr(wordLeft, childNode);
                    break;
                }
            }
        }
        // 没有首字母相同的孩子,则将其变为子节点
        if (!isFind) {
            Node newNode = new Node(true, 1, wordLeft);
            node.addChild(wordLeft, newNode);
        }
    }

    // 添加单词
    public void add(String word) {
        try {
            writeLock.lock();
            addStr(word, root);
        }finally {
            writeLock.unlock();
        }

    }

    // 在节点中查找字串
    private boolean findStr(String word, Node node) {
        boolean isMatch = true;
        String wordLeft = word;
        String str = node.str;
        if (null != str) {
            // 字串与单词不匹配
            if (word.indexOf(str) != 0) {
                isMatch = false;
            } else {
                // 匹配,则计算剩余单词(从匹配的后一位到最后一位)
                wordLeft = word.substring(str.length());
            }
        }
        // 如果匹配
        if (isMatch) {
            // 如果还有剩余单词长度
            if (wordLeft.length() > 0) {
                if (node.childs.size() > 0) {
                    // 遍历孩子继续找
                    for (String key : node.childs.keySet()) {
                        Node childNode = node.childs.get(key);
                        //递归
                        boolean isChildFind = findStr(wordLeft, childNode);
                        if (isChildFind) {
                            return true;
                        }
                    }
                }else {
                    //如果没有子节点了,返回false
                    return false;
                }
            } else {
                // 没有剩余单词长度,说明已经匹配完毕,直接返回节点是否为单词,匹配到即便符合前缀,也不能算单词
                return node.isWord;
            }
        }
        return false;
    }

    // 查找单词
    public boolean find(String word) {
        try {
            readLock.lock();
            return findStr(word, root);
        }finally {
            readLock.unlock();
        }

    }

    // 统计子节点字串单词数
    private int countChildStr(String prefix, Node node) {
        // 遍历孩子
        for (String key : node.childs.keySet()) {
            Node childNode = node.childs.get(key);
            // 匹配子节点
            int childCount = countStr(prefix, childNode);
            if (childCount != 0) {
                return childCount;
            }
        }
        return 0;
    }

    // 统计字串单词数
    private int countStr(String prefix, Node node) {
        String str = node.str;
        // 非根结点
        if (null != str) {
            // 前缀与字串不匹配
            if (prefix.indexOf(str) != 0 && str.indexOf(prefix) != 0) {
                return 0;
                // 前缀匹配字串,且前缀较短
            } else if (str.indexOf(prefix) == 0) {
                // 找到目标节点,返回单词数
                return node.count;
                // 前缀匹配字串,且字串较短
            } else if (prefix.indexOf(str) == 0) {
                // 剩余字串继续匹配子节点
                String prefixLeft = prefix.substring(str.length());
                if (prefixLeft.length() > 0) {
                    return countChildStr(prefixLeft, node);
                }
            }
        } else {
            // 根结点,直接找其子孙
            return countChildStr(prefix, node);
        }
        return 0;
    }

    // 统计前缀单词数
    public int count(String prefix) {
        // 处理特殊情况
        try {
            readLock.lock();
            if (null == prefix || prefix.trim().isEmpty()) {
                return root.count;
            }
            // 从根结点往下匹配
            return countStr(prefix, root);
        }finally {
            readLock.unlock();
        }

    }

    // 打印节点
    private void printNode(Node node, int layer) {
        // 层级递进
        for (int i = 0; i < layer; i++) {
            System.out.print("    ");
        }
        // 打印
        System.out.println(node);
        // 递归打印子节点
        for (String str : node.childs.keySet()) {
            Node child = node.childs.get(str);
            printNode(child, layer + 1);
        }
    }

    // 打印字典树
    public void print() {
        try {
            readLock.lock();
            printNode(root, 0);
        }finally {
            readLock.unlock();
        }

    }
    public static String getRandomString(int length) {
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        //循环length次
        for(int i = 0; i < length; i++){
            //产生0-2个随机数,既与a-z,A-Z,0-9三种可能
//            int number=random.nextInt(3);
            int number = 1;
            long result = 0L;
            switch(number){
                //如果number产生的是数字0;
                case 0:
                    //产生A-Z的ASCII码
                    result = Math.round(Math.random()*25+65);
                    //将ASCII码转换成字符
                    sb.append(String.valueOf((char)result));
                    break;
                case 1:
                    //产生a-z的ASCII码
                    result=Math.round(Math.random()*25+97);
                    sb.append(String.valueOf((char)result));
                    break;
                case 2:
                    //产生0-9的数字
                    sb.append(String.valueOf
                            (new Random().nextInt(10)));
                    break;
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) throws InterruptedException {

        DictionaryTree dt = new DictionaryTree();
        CountDownLatch latch = new CountDownLatch(500);
        Runnable task = new Runnable() {
            @Override
            public void run() {
                dt.add(getRandomString(10));
                latch.countDown();
            }
        };
        ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
        for (int i = 0;i < 500;i++) {
            es.submit(task);
        }
        latch.await();
//        dt.add("interest");
//        dt.add("interesting");
//        dt.add("interested");
//        dt.add("inside");
//        dt.add("insert");
//        dt.add("apple");
//        dt.add("inter");
//        dt.add("interesting");
//        dt.add("aha");
//        dt.add("fuck");
//        dt.add("finish");
//        dt.add("fish");

        dt.print();

        boolean isFind = dt.find("a");
        System.out.println("find a : " + isFind);

        isFind = dt.find("aha");
        System.out.println("find aha : " + isFind);

        int count = dt.count("inter");
        System.out.println("count prefix inter : " + count);
        es.shutdown();
    }
}

运行结果:

str : null, isWord : false, count : 500 str : a, isWord : false, count : 13 str : aynktxfyv, isWord : true, count : 1 str : qsmxpqlhe, isWord : true, count : 1 str : jvtrvhvlp, isWord : true, count : 1 str : dfakhoyje, isWord : true, count : 1 str : myclcdtmm, isWord : true, count : 1 str : cdpenahjw, isWord : true, count : 1 str : fvxoyszdo, isWord : true, count : 1 str : giobhpfeu, isWord : true, count : 1 str : i, isWord : false, count : 2 str : xaakwfbn, isWord : true, count : 1 str : goeeixla, isWord : true, count : 1 str : vthbspcbw, isWord : true, count : 1 str : stmrgrokg, isWord : true, count : 1 str : tstmujfvm, isWord : true, count : 1 str : b, isWord : false, count : 18 str : ahckiaakm, isWord : true, count : 1 str : ibkxlklnp, isWord : true, count : 1 str : syclxybky, isWord : true, count : 1 str : qustarhze, isWord : true, count : 1 str : u, isWord : false, count : 3 str : ohlifgck, isWord : true, count : 1 str : lopecahh, isWord : true, count : 1 str : khclgcyd, isWord : true, count : 1 str : ktybpnhgj, isWord : true, count : 1 str : w, isWord : false, count : 2 str : xogivfbc, isWord : true, count : 1 str : jjdmtiel, isWord : true, count : 1 str : x, isWord : false, count : 3 str : qimqqitp, isWord : true, count : 1 str : giwcjqvv, isWord : true, count : 1 str : tpmunncg, isWord : true, count : 1 str : npixbfxgq, isWord : true, count : 1 str : j, isWord : false, count : 2 str : ktvhgytz, isWord : true, count : 1 str : jcxrihjw, isWord : true, count : 1 str : lcsrejxcj, isWord : true, count : 1 str : ezxizwqnx, isWord : true, count : 1 str : c, isWord : false, count : 23 str : bvbV**cmi, isWord : true, count : 1 str : a, isWord : false, count : 2 str : ohbsqhyv, isWord : true, count : 1 str : pgrhuhvj, isWord : true, count : 1 str : fqdmrupqi, isWord : true, count : 1 str : xzkqsrfnl, isWord : true, count : 1 str : qnjvgwlqm, isWord : true, count : 1 str : ylxqipkii, isWord : true, count : 1 str : vxmxaogax, isWord : true, count : 1 str : o, isWord : false, count : 4 str : adtoabkk, isWord : true, count : 1 str : evgmvyox, isWord : true, count : 1 str : obippxob, isWord : true, count : 1 str : wmkmtjln, isWord : true, count : 1 str : myxiuxpse, isWord : true, count : 1 str : jwyypaxpj, isWord : true, count : 1 str : t, isWord : false, count : 2 str : rqbhnnre, isWord : true, count : 1 str : gncvbqsf, isWord : true, count : 1 str : rjfghlovy, isWord : true, count : 1 str : u, isWord : false, count : 2 str : vnzghtcf, isWord : true, count : 1 str : ygicbibt, isWord : true, count : 1 str : w, isWord : false, count : 2 str : ebxnwiba, isWord : true, count : 1 str : jhnsjjfu, isWord : true, count : 1 str : z, isWord : false, count : 2 str : gcxchyhj, isWord : true, count : 1 str : fmgotnym, isWord : true, count : 1 str : d, isWord : false, count : 20 str : b, isWord : false, count : 2 str : isoprvlr, isWord : true, count : 1 str : kwwchnhv, isWord : true, count : 1 str : g, isWord : false, count : 2 str : ubhtbbdb, isWord : true, count : 1 str : thnfdskg, isWord : true, count : 1 str : thgudyfqy, isWord : true, count : 1 str : nxfvflgyf, isWord : true, count : 1 str : i, isWord : false, count : 2 str : hhfflsmk, isWord : true, count : 1 str : botkntno, isWord : true, count : 1 str : k, isWord : false, count : 2 str : wwetdhxd, isWord : true, count : 1 str : kmksjtvo, isWord : true, count : 1 str : ahfxtzfwy, isWord : true, count : 1 str : ennqllhgu, isWord : true, count : 1 str : ukxjneotd, isWord : true, count : 1 str : o, isWord : false, count : 2 str : pfwgcijy, isWord : true, count : 1 str : buchntfb, isWord : true, count : 1 str : cxdouqbfr, isWord : true, count : 1 str : wlfjthkap, isWord : true, count : 1 str : xyxywylpf, isWord : true, count : 1 str : hzgV**afs, isWord : true, count : 1 str : zjkpjzttb, isWord : true, count : 1 str : e, isWord : false, count : 20 str : b, isWord : false, count : 2 str : uctinobl, isWord : true, count : 1 str : bbqjgdup, isWord : true, count : 1 str : fbwjnhbej, isWord : true, count : 1 str : i, isWord : false, count : 2 str : rvpojxdf, isWord : true, count : 1 str : gsydkjyn, isWord : true, count : 1 str : j, isWord : false, count : 2 str : usflntug, isWord : true, count : 1 str : fkqfyhyb, isWord : true, count : 1 str : omdkokrvr, isWord : true, count : 1 str : qhvvhucmb, isWord : true, count : 1 str : drqpbvhlx, isWord : true, count : 1 str : vvtrgqsdy, isWord : true, count : 1 str : lwqlxzpwg, isWord : true, count : 1 str : sifbolcpi, isWord : true, count : 1 str : tragbqswl, isWord : true, count : 1 str : awfsciltt, isWord : true, count : 1 str : w, isWord : false, count : 3 str : icvimuaz, isWord : true, count : 1 str : nxluecgg, isWord : true, count : 1 str : tdqioyrz, isWord : true, count : 1 str : hgnbncypo, isWord : true, count : 1 str : untsoedek, isWord : true, count : 1 str : f, isWord : false, count : 19 str : ffzeobwsr, isWord : true, count : 1 str : s, isWord : false, count : 3 str : dclynbdk, isWord : true, count : 1 str : gmpwfjrj, isWord : true, count : 1 str : ewuqujtw, isWord : true, count : 1 str : mfrlmqmfr, isWord : true, count : 1 str : d, isWord : false, count : 6 str : nqrngqrb, isWord : true, count : 1 str : gfyoguqf, isWord : true, count : 1 str : esyjhfzm, isWord : true, count : 1 str : pejvnpqc, isWord : true, count : 1 str : qkgwhdjm, isWord : true, count : 1 str : mmyrwluh, isWord : true, count : 1 str : bkfagjiri, isWord : true, count : 1 str : psplkjufd, isWord : true, count : 1 str : h, isWord : false, count : 2 str : wutdthld, isWord : true, count : 1 str : dwpjrjbw, isWord : true, count : 1 str : k, isWord : false, count : 2 str : mhgksicu, isWord : true, count : 1 str : wcaxwdnq, isWord : true, count : 1 str : nxuyasjgx, isWord : true, count : 1 str : gewomfbwu, isWord : true, count : 1 str : g, isWord : false, count : 23 str : i, isWord : false, count : 2 str : zjjsubas, isWord : true, count : 1 str : rbcgawsc, isWord : true, count : 1 str : geyfehanp, isWord : true, count : 1 str : j, isWord : false, count : 2 str : gvitwrvd, isWord : true, count : 1 str : amfrozmf, isWord : true, count : 1 str : ssqfbuwbv, isWord : true, count : 1 str : djyvjlrsi, isWord : true, count : 1 str : qvvpdvicc, isWord : true, count : 1 str : lugpxdvej, isWord : true, count : 1 str : fuaxzbyhx, isWord : true, count : 1 str : o, isWord : false, count : 2 str : pjpwkbzh, isWord : true, count : 1 str : ncrwrpho, isWord : true, count : 1 str : prardfgdn, isWord : true, count : 1 str : vcnplwbie, isWord : true, count : 1 str : u, isWord : false, count : 2 str : rzmconay, isWord : true, count : 1 str : esvrfjjv, isWord : true, count : 1 str : kjhyxrrwn, isWord : true, count : 1 str : y, isWord : false, count : 2 str : tidbmpvw, isWord : true, count : 1 str : bpbgagsp, isWord : true, count : 1 str : z, isWord : false, count : 3 str : aeirvyss, isWord : true, count : 1 str : hhkvdvtj, isWord : true, count : 1 str : fvkniezk, isWord : true, count : 1 str : xsqsdhnks, isWord : true, count : 1 str : h, isWord : false, count : 22 str : a, isWord : false, count : 2 str : ghnrudof, isWord : true, count : 1 str : ckkpnlwh, isWord : true, count : 1 str : c, isWord : false, count : 2 str : bgcieeix, isWord : true, count : 1 str : uinorkfm, isWord : true, count : 1 str : d, isWord : false, count : 2 str : cpsughmq, isWord : true, count : 1 str : kmftctvq, isWord : true, count : 1 str : g, isWord : false, count : 2 str : begltzfb, isWord : true, count : 1 str : cmrqgjsj, isWord : true, count : 1 str : j, isWord : false, count : 2 str : wcbqscvq, isWord : true, count : 1 str : hknrmaop, isWord : true, count : 1 str : nxpdvqwcp, isWord : true, count : 1 str : l, isWord : false, count : 2 str : qsxomrcy, isWord : true, count : 1 str : fnjeyout, isWord : true, count : 1 str : xkvtoggor, isWord : true, count : 1 str : hehvmiobd, isWord : true, count : 1 str : s, isWord : false, count : 2 str : ljnwwidx, isWord : true, count : 1 str : nygyfssr, isWord : true, count : 1 str : v, isWord : false, count : 2 str : jytrtose, isWord : true, count : 1 str : encidcbk, isWord : true, count : 1 str : yxwenwbjo, isWord : true, count : 1 str : ie, isWord : false, count : 2 str : ndcsikr, isWord : true, count : 1 str : pkczlwa, isWord : true, count : 1 str : i, isWord : false, count : 21 str : zxtdgcsug, isWord : true, count : 1 str : kgdvcgjwa, isWord : true, count : 1 str : goimnjuxe, isWord : true, count : 1 str : d, isWord : false, count : 2 str : vsnbmygo, isWord : true, count : 1 str : nellduoq, isWord : true, count : 1 str : vsmnbrczt, isWord : true, count : 1 str : ibeuypnkt, isWord : true, count : 1 str : l, isWord : false, count : 2 str : lskozfen, isWord : true, count : 1 str : edguybhq, isWord : true, count : 1 str : ouflycyoe, isWord : true, count : 1 str : ftoyvxhao, isWord : true, count : 1 str : eistonoes, isWord : true, count : 1 str : q, isWord : false, count : 2 str : wdhyditq, isWord : true, count : 1 str : fbfrhzmr, isWord : true, count : 1 str : wkmrtnvjg, isWord : true, count : 1 str : s, isWord : false, count : 4 str : finqjpic, isWord : true, count : 1 str : akdlvdvh, isWord : true, count : 1 str : kvnqexnm, isWord : true, count : 1 str : lshsmdxv, isWord : true, count : 1 str : bplhteiyc, isWord : true, count : 1 str : cetvqlbod, isWord : true, count : 1 str : j, isWord : false, count : 24 str : yqxlnrimk, isWord : true, count : 1 str : dbrgxlhdg, isWord : true, count : 1 str : mtsasvlyp, isWord : true, count : 1 str : c, isWord : false, count : 2 str : nhowgxzt, isWord : true, count : 1 str : jacfwjsi, isWord : true, count : 1 str : uwuhwcaxp, isWord : true, count : 1 str : g, isWord : false, count : 3 str : ijmffwnq, isWord : true, count : 1 str : ceafgjft, isWord : true, count : 1 str : xvxtqffh, isWord : true, count : 1 str : j, isWord : false, count : 2 str : datglbgb, isWord : true, count : 1 str : psofjwbu, isWord : true, count : 1 str : xwnlgjyln, isWord : true, count : 1 str : o, isWord : false, count : 3 str : uicqpgny, isWord : true, count : 1 str : kfrruuhh, isWord : true, count : 1 str : ajdfqsft, isWord : true, count : 1 str : sfsdflxgq, isWord : true, count : 1 str : igfkxtwfm, isWord : true, count : 1 str : ztxjbfluo, isWord : true, count : 1 str : q, isWord : false, count : 2 str : oovyrzen, isWord : true, count : 1 str : nwrsfsjb, isWord : true, count : 1 str : rufxxbisb, isWord : true, count : 1 str : v, isWord : false, count : 2 str : pxkvluon, isWord : true, count : 1 str : vcyiuooi, isWord : true, count : 1 str : fogdyyarp, isWord : true, count : 1 str : k, isWord : false, count : 20 str : uiyhichvr, isWord : true, count : 1 str : mekbpgkkh, isWord : true, count : 1 str : i, isWord : false, count : 2 str : dbahjpps, isWord : true, count : 1 str : slgbmcoy, isWord : true, count : 1 str : recqutazs, isWord : true, count : 1 str : zabvtxmbx, isWord : true, count : 1 str : p, isWord : false, count : 3 str : mgzbigsj, isWord : true, count : 1 str : rsnsneku, isWord : true, count : 1 str : nysqhncd, isWord : true, count : 1 str : yegghtvoe, isWord : true, count : 1 str : ebqtzmlsw, isWord : true, count : 1 str : cw, isWord : false, count : 2 str : yppoojo, isWord : true, count : 1 str : qqiepin, isWord : true, count : 1 str : lnpiibvry, isWord : true, count : 1 str : qkldejdeg, isWord : true, count : 1 str : v, isWord : false, count : 2 str : hcakcrip, isWord : true, count : 1 str : pyocmnxr, isWord : true, count : 1 str : aqsvubqrh, isWord : true, count : 1 str : fwhlgothm, isWord : true, count : 1 str : gtkunybjp, isWord : true, count : 1 str : l, isWord : false, count : 16 str : tykwoeyma, isWord : true, count : 1 str : foenehshj, isWord : true, count : 1 str : ykodlbvhk, isWord : true, count : 1 str : dpojvwruz, isWord : true, count : 1 str : pnjuamwih, isWord : true, count : 1 str : wfovkcpea, isWord : true, count : 1 str : uqbxvhcej, isWord : true, count : 1 str : h, isWord : false, count : 3 str : q, isWord : false, count : 2 str : xcmsyjw, isWord : true, count : 1 str : gtybdgz, isWord : true, count : 1 str : cwdhfljl, isWord : true, count : 1 str : asirzknwb, isWord : true, count : 1 str : j, isWord : false, count : 2 str : weavcfwf, isWord : true, count : 1 str : axobpyzy, isWord : true, count : 1 str : bssldvnod, isWord : true, count : 1 str : n, isWord : false, count : 2 str : yigypswa, isWord : true, count : 1 str : voinhset, isWord : true, count : 1 str : m, isWord : false, count : 20 str : a, isWord : false, count : 2 str : jzxvsbuq, isWord : true, count : 1 str : bnsdwxmw, isWord : true, count : 1 str : b, isWord : false, count : 2 str : evpbddpa, isWord : true, count : 1 str : ynqeqzgc, isWord : true, count : 1 str : zbdvbvcnl, isWord : true, count : 1 str : d, isWord : false, count : 2 str : ylwyxlkc, isWord : true, count : 1 str : idwxbtei, isWord : true, count : 1 str : omtbqtxei, isWord : true, count : 1 str : sdqgwgnjo, isWord : true, count : 1 str : wlmkkzwqb, isWord : true, count : 1 str : qdxpxsowd, isWord : true, count : 1 str : p, isWord : false, count : 2 str : namqmvte, isWord : true, count : 1 str : ukhcsuow, isWord : true, count : 1 str : yclsmbgvb, isWord : true, count : 1 str : u, isWord : false, count : 2 str : juovneoh, isWord : true, count : 1 str : vmttfvos, isWord : true, count : 1 str : v, isWord : false, count : 2 str : teprigjs, isWord : true, count : 1 str : qylrswml, isWord : true, count : 1 str : x, isWord : false, count : 2 str : fiuthpwm, isWord : true, count : 1 str : jjgmgxjy, isWord : true, count : 1 str : n, isWord : false, count : 18 str : wxdkvgywg, isWord : true, count : 1 str : c, isWord : false, count : 2 str : eebdkkkd, isWord : true, count : 1 str : cqdlojgh, isWord : true, count : 1 str : tudnypngd, isWord : true, count : 1 str : d, isWord : false, count : 2 str : qjvbeqoy, isWord : true, count : 1 str : gviclxjq, isWord : true, count : 1 str : vpwcaekjx, isWord : true, count : 1 str : f, isWord : false, count : 2 str : yfwyxsru, isWord : true, count : 1 str : vvtmjnlq, isWord : true, count : 1 str : olnrywqvo, isWord : true, count : 1 str : iosebaodr, isWord : true, count : 1 str : uwmoitczp, isWord : true, count : 1 str : xrsbofbtt, isWord : true, count : 1 str : ngvnhrbfs, isWord : true, count : 1 str : y, isWord : false, count : 3 str : vtqvwssx, isWord : true, count : 1 str : lplphgmh, isWord : true, count : 1 str : tcotbygo, isWord : true, count : 1 str : jdxvxxptx, isWord : true, count : 1 str : o, isWord : false, count : 14 str : kvhhlbdab, isWord : true, count : 1 str : bumffivtn, isWord : true, count : 1 str : plnebqeao, isWord : true, count : 1 str : mpwjixmmt, isWord : true, count : 1 str : tpsqklver, isWord : true, count : 1 str : u, isWord : false, count : 2 str : qpxxhiyj, isWord : true, count : 1 str : lkbfgrjq, isWord : true, count : 1 str : dkoejecvg, isWord : true, count : 1 str : nyobqxjks, isWord : true, count : 1 str : fcjhwdlcg, isWord : true, count : 1 str : rqdudbfee, isWord : true, count : 1 str : o, isWord : false, count : 3 str : rcysotjt, isWord : true, count : 1 str : sbxohfbd, isWord : true, count : 1 str : pofgixiv, isWord : true, count : 1 str : p, isWord : false, count : 27 str : nqdtikyvx, isWord : true, count : 1 str : b, isWord : false, count : 2 str : kpkqcpql, isWord : true, count : 1 str : fznlible, isWord : true, count : 1 str : c, isWord : false, count : 2 str : mhterbxy, isWord : true, count : 1 str : debpoecx, isWord : true, count : 1 str : ustwlwqjd, isWord : true, count : 1 str : jowdmdbvt, isWord : true, count : 1 str : k, isWord : false, count : 4 str : efrfnyce, isWord : true, count : 1 str : bkpoopsa, isWord : true, count : 1 str : dqyuumto, isWord : true, count : 1 str : ieubnydl, isWord : true, count : 1 str : ixrtmuhnb, isWord : true, count : 1 str : o, isWord : false, count : 2 str : ykygvgcy, isWord : true, count : 1 str : noqmgruu, isWord : true, count : 1 str : q, isWord : false, count : 2 str : xurbngrr, isWord : true, count : 1 str : zrmcwtqs, isWord : true, count : 1 str : hxlkusrvz, isWord : true, count : 1 str : mbspmgiux, isWord : true, count : 1 str : s, isWord : false, count : 2 str : cmklndaf, isWord : true, count : 1 str : tqjxoxve, isWord : true, count : 1 str : t, isWord : false, count : 2 str : zfmitvyj, isWord : true, count : 1 str : ildpdzmx, isWord : true, count : 1 str : v, isWord : false, count : 2 str : hhscedqv, isWord : true, count : 1 str : lbtgvjcs, isWord : true, count : 1 str : y, isWord : false, count : 2 str : pxtrjgqy, isWord : true, count : 1 str : jqkotwhe, isWord : true, count : 1 str : pizddnvmh, isWord : true, count : 1 str : q, isWord : false, count : 15 str : byhsnctqd, isWord : true, count : 1 str : jhnvdbkdi, isWord : true, count : 1 str : t, isWord : false, count : 2 str : zvnemtiq, isWord : true, count : 1 str : ebrcpsqe, isWord : true, count : 1 str : u, isWord : false, count : 4 str : npscqpop, isWord : true, count : 1 str : ccmypnca, isWord : true, count : 1 str : movdxpdf, isWord : true, count : 1 str : bhinjrcu, isWord : true, count : 1 str : fvmiivshy, isWord : true, count : 1 str : gyficrern, isWord : true, count : 1 str : nrnljmnsl, isWord : true, count : 1 str : pjllpuili, isWord : true, count : 1 str : wvvlevgqd, isWord : true, count : 1 str : o, isWord : false, count : 2 str : jpvlsbsu, isWord : true, count : 1 str : rudrudqj, isWord : true, count : 1 str : r, isWord : false, count : 20 str : ilubscsym, isWord : true, count : 1 str : r, isWord : false, count : 3 str : neyqpuhc, isWord : true, count : 1 str : jvlyynuu, isWord : true, count : 1 str : sxucdpiq, isWord : true, count : 1 str : s, isWord : false, count : 2 str : jmyigesh, isWord : true, count : 1 str : vcwubtml, isWord : true, count : 1 str : oxllpefko, isWord : true, count : 1 str : bcvwsogdd, isWord : true, count : 1 str : pcvotvpuq, isWord : true, count : 1 str : f, isWord : false, count : 2 str : vibimlag, isWord : true, count : 1 str : evrpfumm, isWord : true, count : 1 str : egsvvlovf, isWord : true, count : 1 str : w, isWord : false, count : 4 str : odihhdvq, isWord : true, count : 1 str : binhvwac, isWord : true, count : 1 str : dgtxcylv, isWord : true, count : 1 str : haegudbo, isWord : true, count : 1 str : xkqnixyfi, isWord : true, count : 1 str : k, isWord : false, count : 3 str : fyckhlee, isWord : true, count : 1 str : cdjtcjrq, isWord : true, count : 1 str : dhyejwsg, isWord : true, count : 1 str : s, isWord : false, count : 25 str : kcwlvxxuc, isWord : true, count : 1 str : b, isWord : false, count : 2 str : blidfzih, isWord : true, count : 1 str : vgdddnmm, isWord : true, count : 1 str : c, isWord : false, count : 4 str : cxgtfkdo, isWord : true, count : 1 str : h, isWord : false, count : 2 str : wuvcunq, isWord : true, count : 1 str : inaflrp, isWord : true, count : 1 str : tussjbav, isWord : true, count : 1 str : e, isWord : false, count : 2 str : cvvorcwz, isWord : true, count : 1 str : amlthaxk, isWord : true, count : 1 str : ldkxnmril, isWord : true, count : 1 str : gqlwnjmlf, isWord : true, count : 1 str : vqkhldfdw, isWord : true, count : 1 str : mewetpryj, isWord : true, count : 1 str : q, isWord : false, count : 4 str : oltgrppw, isWord : true, count : 1 str : c, isWord : false, count : 2 str : pkgljhj, isWord : true, count : 1 str : ctfidpz, isWord : true, count : 1 str : whxisjbg, isWord : true, count : 1 str : oduwvijdn, isWord : true, count : 1 str : xhdxhnspi, isWord : true, count : 1 str : s, isWord : false, count : 2 str : ohsvwemq, isWord : true, count : 1 str : tfitotfu, isWord : true, count : 1 str : rrdthzbqq, isWord : true, count : 1 str : y, isWord : false, count : 2 str : iubthgjs, isWord : true, count : 1 str : ejccuiwh, isWord : true, count : 1 str : jflguhwgh, isWord : true, count : 1 str : t, isWord : false, count : 14 str : dibehwpvb, isWord : true, count : 1 str : c, isWord : false, count : 2 str : hzmoycnt, isWord : true, count : 1 str : rdbppojv, isWord : true, count : 1 str : yygjpogbz, isWord : true, count : 1 str : zuusmshca, isWord : true, count : 1 str : ieuqncuud, isWord : true, count : 1 str : rwsvnhcmw, isWord : true, count : 1 str : otghtuvqo, isWord : true, count : 1 str : ugasrmtuy, isWord : true, count : 1 str : j, isWord : false, count : 2 str : nxdcehvh, isWord : true, count : 1 str : rpmyapuw, isWord : true, count : 1 str : lkoswttyr, isWord : true, count : 1 str : m, isWord : false, count : 2 str : lmdbsqml, isWord : true, count : 1 str : iqrbwxfx, isWord : true, count : 1 str : u, isWord : false, count : 20 str : xbhssncfj, isWord : true, count : 1 str : uwpofcpoc, isWord : true, count : 1 str : d, isWord : false, count : 2 str : jufrmoxn, isWord : true, count : 1 str : yxlsgsku, isWord : true, count : 1 str : qvkkobbwj, isWord : true, count : 1 str : m, isWord : false, count : 2 str : yclcwpve, isWord : true, count : 1 str : lfvbnafq, isWord : true, count : 1 str : cisxawvgp, isWord : true, count : 1 str : n, isWord : false, count : 2 str : qomvggve, isWord : true, count : 1 str : eoqcvkjc, isWord : true, count : 1 str : jlopfvfyn, isWord : true, count : 1 str : s, isWord : false, count : 3 str : iultquie, isWord : true, count : 1 str : glsdcszb, isWord : true, count : 1 str : hvtacxck, isWord : true, count : 1 str : w, isWord : false, count : 2 str : opldtdkw, isWord : true, count : 1 str : fmuoxxdy, isWord : true, count : 1 str : vpcadsief, isWord : true, count : 1 str : tsrhbsivm, isWord : true, count : 1 str : aybxoetvn, isWord : true, count : 1 str : fcvrmdfje, isWord : true, count : 1 str : v, isWord : false, count : 21 str : a, isWord : false, count : 2 str : rprkekdt, isWord : true, count : 1 str : qvcteorp, isWord : true, count : 1 str : gtqhbewsb, isWord : true, count : 1 str : b, isWord : false, count : 2 str : bbvdfabi, isWord : true, count : 1 str : wybqnobb, isWord : true, count : 1 str : lswdvufbu, isWord : true, count : 1 str : d, isWord : false, count : 2 str : cgvkugmv, isWord : true, count : 1 str : hdyvqvso, isWord : true, count : 1 str : e, isWord : false, count : 2 str : xjhewjfn, isWord : true, count : 1 str : ubusbnck, isWord : true, count : 1 str : jrkyuqfhy, isWord : true, count : 1 str : uxwlhbcdm, isWord : true, count : 1 str : v, isWord : false, count : 2 str : lwpqrkxk, isWord : true, count : 1 str : qstkbtvg, isWord : true, count : 1 str : fbkrymshl, isWord : true, count : 1 str : cuvyidufi, isWord : true, count : 1 str : z, isWord : false, count : 2 str : insawsph, isWord : true, count : 1 str : disumgpv, isWord : true, count : 1 str : oeilidftj, isWord : true, count : 1 str : pqvqhmwxk, isWord : true, count : 1 str : hbplpplns, isWord : true, count : 1 str : w, isWord : false, count : 19 str : c, isWord : false, count : 2 str : htlmjxdb, isWord : true, count : 1 str : kcytuqno, isWord : true, count : 1 str : f, isWord : false, count : 2 str : bfqitldc, isWord : true, count : 1 str : mghqdaok, isWord : true, count : 1 str : g, isWord : false, count : 2 str : phytwsfg, isWord : true, count : 1 str : gpclxbve, isWord : true, count : 1 str : h, isWord : false, count : 2 str : snichuuh, isWord : true, count : 1 str : ajqnnvnb, isWord : true, count : 1 str : bmdkoeteg, isWord : true, count : 1 str : m, isWord : false, count : 2 str : ssnhnquu, isWord : true, count : 1 str : yxuymjci, isWord : true, count : 1 str : ltwfkipuz, isWord : true, count : 1 str : q, isWord : false, count : 2 str : qmaofhux, isWord : true, count : 1 str : izjglqwe, isWord : true, count : 1 str : dkuttvjfq, isWord : true, count : 1 str : vktomypri, isWord : true, count : 1 str : rpbpttgcv, isWord : true, count : 1 str : ksrdoqsgq, isWord : true, count : 1 str : phqeihumc, isWord : true, count : 1 str : x, isWord : false, count : 23 str : rkfwgdrtg, isWord : true, count : 1 str : nbkiqhfiw, isWord : true, count : 1 str : c, isWord : false, count : 2 str : qoxcdbqn, isWord : true, count : 1 str : fknahuuc, isWord : true, count : 1 str : gbxmsbtga, isWord : true, count : 1 str : joaommefq, isWord : true, count : 1 str : yroekddqh, isWord : true, count : 1 str : uihdqbzxy, isWord : true, count : 1 str : o, isWord : false, count : 2 str : uremdykm, isWord : true, count : 1 str : hnbikpte, isWord : true, count : 1 str : q, isWord : false, count : 2 str : emgreolm, isWord : true, count : 1 str : ssxplvcl, isWord : true, count : 1 str : s, isWord : false, count : 2 str : ffnphust, isWord : true, count : 1 str : aiijhflt, isWord : true, count : 1 str : hwfhcwjzy, isWord : true, count : 1 str : t, isWord : false, count : 2 str : fpeymosg, isWord : true, count : 1 st

主要应用场景:

搜索提示框,不过这些功能现在其实大部分被搜索引擎(如elasticsearch等)用的已经很成熟了,这篇文章也算是一个对树使用的非常好的例子.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档