一个简单的统计问题(解决方案: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());

原文地址:https://www.cnblogs.com/panzi/p/10412645.html

时间: 2024-11-13 09:59:23

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

HDU1251 统计难题 【trie树】

统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Submission(s): 17302    Accepted Submission(s): 7464 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的

-一个简单的数据缓存解决方案

最近做了一个聊天室系统,系统有N个聊天室,在并发量很大的情况下,如果用户聊天记录直接写入MySql的话,对数据库的冲击会很大.这里我写了个简单的解决方案:聊天数据先存入redis的队列中,然后用crontab每隔1分钟执行PHP脚本,把数据从redis队列中"批量"移到mysql.当有多条插入语句时,把数据拼装成1条insert语句,减少数据库的操作次数. 1. 配置文件 config.php <?php function dbMessageConfig(){ //用户信息库表的

一个简单高效的多线程解决方案

import java.io.File; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; /**  * 多线程抓取数据的简单程序  */ public class MultithreadFetcher { /** 阻塞队列的最大长度,防止内存溢出.  */ pub

字典树Trie树

一.字典树 字典树--Trie树,又称为前缀树(Prefix Tree).单词查找树或键树,是一种多叉树结构. 上图是一棵Trie树,表示了关键字集合{"a", "to", "tea", "ted", "ten", "i", "in", "inn"} .从上图可以归纳出Trie树的基本性质: 1. 根节点不包含字符,除根节点外的每一个子节点都包含一

利用Trie树求多个字符串编辑距离的进一步优化

1.引言 题目的意思应该是:在一个给定的字典中,求与给定的字符串的编辑距离不大于2的所有的单词.原先写过两片关于此问题的文章,那两片篇章文章给出两种解决思路:其一是暴力求解法,这种方法最容易想到.就是将词典中的词一一与给定的字符串计算编辑距离,不大于2的输出,大于2的舍弃,这种方法思路简单但是很费时间.其二根据词典中这些词之间的编辑距离建立一个以单词为节点的Trie树,遍历的时候,通过计算根节点与给定字符串的编辑距离就可以排除掉一部分分支了,然后继续计算该字符串与剩余的分支的根的编辑距离,继续排

查找(二)简单清晰的B树、Trie树具体解释

查找(二) 散列表 散列表是普通数组概念的推广.因为对普通数组能够直接寻址,使得能在O(1)时间内訪问数组中的任何位置.在散列表中,不是直接把keyword作为数组的下标,而是依据keyword计算出对应的下标. 使用散列的查找算法分为两步.第一步是用散列函数将被查找的键转化为数组的一个索引. 我们须要面对两个或多个键都会散列到同样的索引值的情况.因此,第二步就是一个处理碰撞冲突的过程,由两种经典解决碰撞的方法:拉链法和线性探測法. 散列表是算法在时间和空间上作出权衡的经典样例. 假设没有内存限

Trie树的简单描述(需后续总结)

http://www.cnblogs.com/pony1993/archive/2012/07/18/2596730.html 字典树(Trie树) 字典树,又称单词查找树,Trie树,是一种树形结构,典型应用是用于统计,排序和保存大量的字符串,所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用字符串的公共前缀来节约存储空间,最大限度的减少无谓的字符串比较,查询效率比哈希表高. 它有三个基本性质,根节点不包含字符,除根节点外每一个节点都只包含一个字符,从根节点到某一节点,路径上经过的字符连

查找(二)简单清晰的B树、Trie树详解

查找(二) 散列表 散列表是普通数组概念的推广.由于对普通数组可以直接寻址,使得能在O(1)时间内访问数组中的任意位置.在散列表中,不是直接把关键字作为数组的下标,而是根据关键字计算出相应的下标. 使用散列的查找算法分为两步.第一步是用散列函数将被查找的键转化为数组的一个索引. 我们需要面对两个或多个键都会散列到相同的索引值的情况.因此,第二步就是一个处理碰撞冲突的过程,由两种经典解决碰撞的方法:拉链法和线性探测法. 散列表是算法在时间和空间上作出权衡的经典例子. 如果没有内存限制,我们可以直接

【数据结构】字典树/Trie树/前缀树 - 字符串的统计、排序和保存

字典树 描述 字典树,又称单词查找树.Trie树.前缀树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计.排序和保存大量的字符串(但不仅限于字符串). 常见操作有插入和查找,删除操作少见. 性质 根节点不包含字符 除根节点外每一个节点都只包含一个字符 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串 每个节点的所有子节点包含的字符都不相同 优点 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 查询效率比哈希树高 自带字典序排序 直接判断重复,或者记