文档章节

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

算法之名
 算法之名
发布于 10/21 23:47
字数 7485
阅读 67
收藏 0

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

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

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

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了.

// 在节点中查找字串
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()两个方法的互相调用,其实就是我只要找到完全匹配子节点的数量就可以得到结果.他的时间复杂度也是非常的低.不需要一个个的去到叶节点去累加,因为上层节点已经有他的全部单词节点节点的数量.(上层节点也可能是一个单词,并非只是叶节点)

// 统计子节点字串单词数
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 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);
}
public void addChild(String key, Node node) {
    childs.put(key, node);
    node.parent = this;
}

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

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

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

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 : bvbvpncmi, 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 : hzgvpnafs, 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等)用的已经很成熟了,这篇文章也算是一个对树使用的非常好的例子.

© 著作权归作者所有

共有 人打赏支持
算法之名
粉丝 13
博文 107
码字总数 103286
作品 0
广州
私信 提问
Java数据集合性能优化的几点设计启示

java包为我们提供了很多线程安全(部分安全)的数据集合,涉及线程安全就必然会遇到锁争用和效率上的平衡,其实就是读和写的平衡,读是没有问题的,问题在于写,具体就是如何在写的时候,既不...

蓝灰_q
2017/11/18
0
0
ConcurrentDictionary 对决 Dictionary+Locking

在 .NET 4.0 之前,如果我们需要在多线程环境下使用 Dictionary 类,除了自己实现线程同步来保证线程安全之外,我们没有其他选择。 很多开发人员肯定都实现过类似的线程安全方案,可能是通过...

嗯哼9925
2017/12/06
0
0
如何设计并实现一个线程安全的 Map ?(下篇)

在上篇中,我们已经讨论过如何去实现一个 Map 了,并且也讨论了诸多优化点。在下篇中,我们将继续讨论如何实现一个线程安全的 Map。说到线程安全,需要从概念开始说起。 线程安全就是如果你的...

一缕殇流化隐半边冰霜
2017/10/09
0
0
c++常用的数据结构之一  std::map  

1.什么是map? std::map是包含具有唯一键的键值对的排序关联容器。按照使用比较功能对密钥进行排序Compare。搜索,删除和插入操作具有对数复杂性。map通常实现为红黑树。 2.map如何按照键排序...

刘大神
2017/11/02
0
0
深入学习Lock锁(4)——读写锁ReadWriteLock接口

1.简介 如ReentrantLock都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞。读写锁维...

江左煤郎
05/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring应用学习——AOP

1. AOP 1. AOP:即面向切面编程,采用横向抽取机制,取代了传统的继承体系的重复代码问题,如下图所示,性能监控、日志记录等代码围绕业务逻辑代码,而这部分代码是一个高度重复的代码,也就...

江左煤郎
今天
3
0
eclipse的版本

Eclipse各版本代号一览表 Eclipse的设计思想是:一切皆插件。Eclipse核心很小,其它所有功能都以插件的形式附加于Eclipse核心之上。 Eclipse基本内核包括:图形API(SWT/Jface),Java开发环...

mdoo
今天
1
0
SpringBoot源码:启动过程分析(一)

本文主要分析 SpringBoot 的启动过程。 SpringBoot的版本为:2.1.0 release,最新版本。 一.时序图 还是老套路,先把分析过程的时序图摆出来:时序图-SpringBoot2.10启动分析 二.源码分析 首...

Jacktanger
今天
4
0
小白带你认识netty(二)之netty服务端启动(上)

上一章 中的标准netty启动代码中,ServerBootstrap到底是如何启动的呢?这一章我们来瞅下。 server.group(bossGroup, workGroup);server.channel(NioServerSocketChannel.class).optio...

天空小小
今天
3
0
聊聊storm trident batch的分流与聚合

序 本文主要研究一下storm trident batch的分流与聚合 实例 TridentTopology topology = new TridentTopology(); topology.newStream("spout1", spout) .p......

go4it
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部