一个简单的统计问题(解决方案:Trie树)

题目如图

  输入几个不重复的单词和几个前缀,分别统计出单词中包含前缀的个数。

Trie树

  这个题目用到了 Trie 树.它在百度百科中的定义如下:在计算机科学中,Trie,又称字典树、单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。它有3个基本性质:根节点不包含字符,除根节点外每一个节点都只包含一个字符。从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。每个节点的所有子节点包含的字符都不相同。

代码示例

public class TrieNode {
    private char data;
    private int count;
    private boolean isEnding;
    private final TrieNode[] children = new TrieNode[26];

    public void setChildren(TrieNode node, int index) {
        if (children[index] == null) {
            children[index] = node;
        }
    }

    public void setEnding(int index,boolean isEnding){
        children[index].isEnding=isEnding;
        if(!isEnding){
            count++;
        }
    }

    public  void setEnding(boolean isEnding){
        this.isEnding=isEnding;
    }

    public TrieNode getChildren(int index) {
        return children[index];
    }

    public int getCount() {
        return count;
    }

    public boolean isEnding(){
        return isEnding;
    }

    public char getData() {
        return data;
    }

    public TrieNode(char data) {
        this.data = data;
    }
}
public class TrieTree {
    //root node
    private TrieNode root = new TrieNode('/');

    //添加一个数据
    public boolean insert(char[] value) {
        if (value == null || value.length == 0) {
            return false;
        }
        TrieNode p = root;
        int index;
        for (int i = 0; i < value.length; i++) {
            // 减去a得到ASCII码,从0 开始,一直到25
            index = value[i] - 'a';
            //如果这个索引上没有值,重新创建一个
            if (p.getChildren(index) == null) {
                p.setChildren(new TrieNode(value[i]),index);
            }
            p.setEnding(index,false);
            p = p.getChildren(index);
        }
        //循环完之后,最后一个节点的isEnding属性为true
        p.setEnding(true);
        return true;
    }

    //查找一条数据
    public boolean find(char[] value){
        if (value == null || value.length == 0) {
            return false;
        }
        TrieNode p = root;
        int index;
        for (int i=0;i<value.length;i++) {
            index = value[i] - 'a';
            //未找到,返回false
            if (p.getChildren(index) == null) {
                return false;
            }
            p = p.getChildren(index);
        }
        //如果节点是结尾,所以完全匹配,否则是前缀匹配
        return p.isEnding();
    }

    public int count(char[] value) {
        if (value == null || value.length == 0) {
            return 0;
        }
        TrieNode p = root;
        int index;
        for (int i = 0; i < value.length; i++) {
            index = value[i] - 'a';
            //未找到,返回false
            if (p.getChildren(index) == null) {
                return 0;
            }
            p = p.getChildren(index);
        }
        //如果节点是结尾,所以完全匹配,否则是前缀匹配
        return p.isEnding() ? 1 : p.getCount();
    }
}

测试

     TrieTree tree = new TrieTree();
     tree.insert("banana".toCharArray());
     tree.insert("band".toCharArray());
     tree.insert("bee".toCharArray());
     tree.insert("absolute".toCharArray());
     tree.insert("acm".toCharArray());

     //2
     int count1 = tree.count("ba".toCharArray());
     //3
     int count2 = tree.count("b".toCharArray());
     //1
     int count3 = tree.count("band".toCharArray());
     //0
     int count4 = tree.count("abc".toCharArray());

猜你喜欢

转载自www.cnblogs.com/panzi/p/10412645.html