Trie树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

      这里的需求是,给如一组词汇,北京人,北京,武汉,武汉话等等。能够统计“武汉”这个词的词频,输入"武"的时候,能够得到以“武”开头的所有词。实现的代码如下:

package com.dong.util;

import java.util.ArrayList;
import java.util.List; public class Trie {
// 根节点
private final TrieNode root = new TrieNode(' '); // 向trie树中插入一个词
public void insert(String word) {
if (word == null || word.length() == 0) {
return;
}
String left = word;
TrieNode cur = root;
while (left.length() > 0) {
char toInert = left.charAt(0);
TrieNode next = null;
// 如果那个节点不存在的话,将当前节点插入
if (containCharNode(cur.getChild(), toInert) == null) {
next = new TrieNode(toInert);
cur.getChild().add(next);
} else {
next = containCharNode(cur.getChild(), toInert);
}
cur = next;
left = left.substring(1);
if (left.length() == 0) {
cur.setFreq(cur.getFreq() + 1);
}
}
} // 通过前缀查找词,返回包括前缀的所有词。
public List<String> search(String prefix) {
List<String> retList = new ArrayList<String>();
List<String> tempList = new ArrayList<String>();
if (prefix == null || prefix.length() == 0) {
return null;
}
String left = prefix;
TrieNode cur = root;
while (left.length() > 0) {
char toFind = left.charAt(0);
TrieNode next = null;
// 如果那个节点不存在的话,将当前节点插入
if (containCharNode(cur.getChild(), toFind) == null) {
return null;
} else {
next = containCharNode(cur.getChild(), toFind);
if (left.length() == 1) {
cur = next;
break;
}
}
cur = next;
left = left.substring(1); } dfs(cur, new ArrayList<Character>(), tempList);
for (String s : tempList) {
retList.add(prefix + s);
} if (getFreq(prefix) > 0) {
retList.add(prefix); }
return retList;
} // 深度搜索一个trieNode节点下的所有的词
private void dfs(TrieNode root, List<Character> stack, List<String> retList) {
if (root.getChild().size() == 0) {
StringBuffer sb = new StringBuffer();
for (char c : stack) {
sb.append(c);
}
retList.add(sb.toString()); } else {
for (TrieNode r : root.getChild()) {
stack.add(r.getVal());
dfs(r, stack, retList);
stack.remove(stack.size() - 1);
}
} } // 查看一个节点的的子节点是否包含一个字符
public TrieNode containCharNode(List<TrieNode> child, char c) {
TrieNode ret = null;
for (TrieNode temp : child) {
if (temp.getVal() == c) {
ret = temp;
}
}
return ret; } // 得到一个词的词频
public int getFreq(String word) {
if (word == null || word.length() == 0) {
return 0;
}
String left = word;
TrieNode cur = root;
while (left.length() > 0) {
char toFind = left.charAt(0);
TrieNode next = null;
// 如果不存在此节点,返回0
if (containCharNode(cur.getChild(), toFind) == null) {
return 0;
} else {
next = containCharNode(cur.getChild(), toFind);
if (left.length() == 1) {
cur = next;
break;
}
}
cur = next;
left = left.substring(1); }
return cur.getFreq();
} public static String fill(String prefix, ArrayList<Character> stack) {
ArrayList<String> retList = new ArrayList<String>();
StringBuffer sb = new StringBuffer();
sb.append(prefix);
for (char c : stack) {
sb.append(c);
}
return sb.toString(); } public static void main(String[] args) {
Trie t = new Trie();
String[] wordList = { "我晕", "我晕啊", "我不信啊", "我信了", "也是", "这不对啊", "我晕" };
for (String word : wordList) {
t.insert(word);
}
System.out.println(t.search("我晕")); }
} class TrieNode {
// 节点下存放的字符
private char val;
// 一个节点下面的子节点
private List<TrieNode> child;
// 该词的词频
private int freq; public TrieNode(char val) {
child = new ArrayList();
freq = 0;
this.val = val; } public char getVal() {
return val;
} public void setVal(char val) {
this.val = val;
} public List<TrieNode> getChild() {
return child;
} public void setChild(List<TrieNode> child) {
this.child = child;
} public int getFreq() {
return freq;
} public void setFreq(int freq) {
this.freq = freq;
}
}

trie数的实现的更多相关文章

  1. Educational Codeforces Round 23 E. Choosing The Commander trie数

    E. Choosing The Commander time limit per test 2 seconds memory limit per test 256 megabytes input st ...

  2. Trie数 --- 统计公共前缀

    <传送门> 统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others ...

  3. hdu 1251 统计难题(trie 树的简单应用)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251 题意:给你多个字符串,求以某个字符串为前缀的字符串数量. 思路:简单的trie数应用,在trie ...

  4. POJ 3630 Phone List Trie题解

    Trie的应用题目. 本题有两个难点了: 1 动态建立Trie会超时,须要静态建立数组,然后构造树 2 推断的时候注意两种情况: 1) Tire树有133,然后插入13333556的时候.2)插入顺序 ...

  5. 从Trie树到双数组Trie树

    Trie树 原理 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,能在常数时间O(len)内实现插入和查 ...

  6. Trie树/字典树题目(2017今日头条笔试题:异或)

    /* 本程序说明: [编程题] 异或 时间限制:1秒 空间限制:32768K 给定整数m以及n个数字A1,A2,..An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大 ...

  7. Trie树的二三事QWQ

    写在前面 Trie,又称字典树,是一种用于实现字符串快速检索的多叉树结构.Trie的每个结点都拥有若干字符指针,若在插入或检索字符串时扫描到一个字符c,就沿着当前节点的c这个字符指针,走向该指针指向的 ...

  8. 【Luogu3732】[HAOI2017]供给侧改革(Trie树)

    [Luogu3732][HAOI2017]供给侧改革(Trie树) 题面 洛谷 给定一个纯随机的\(01\)串,每次询问\([L,R]\)之间所有后缀两两之间的\(LCP\)的最大值. 题解 一个暴力 ...

  9. POJ 2418 Hardwood Species 【Trie树】

    <题目链接> 题目大意: 给你一堆字符串,让你按字典序输出他们出现的频率. 解题分析: 首先,这是Trie数词频统计的题目,以Trie树的边储存字母,节点存储以该节点结尾的链所代表的字符串 ...

随机推荐

  1. Heartbeat+DRBD+MFS高可用

    Heartbeat+DRBD+MFS高可用. 前言:MFS系统简介 组件名称及作用 管理服务器(Managing Server)   简称Master Server 这个组件的角色是管理整个mfs文件 ...

  2. java重写LinkedList

    LinkedList重写类LinkList.java: import java.util.LinkedList;import java.util.List; public class LinkList ...

  3. python-设计模式:抽象类

    抽象类:用来分离主体框架和局部实现,或将共用和定制解藕.从抽象类继承必须实现所有层级未被实现的抽象方法(被装饰器abstractmethod装饰的方法),否则无法创建实例. 定义抽象类,必须继承ABC ...

  4. 学习笔记:Highcharts

    (Highcharts 167K:  ECharts 354K: jqChart 240K),如果用于网络,Highchart最小 Highcharts 功能强大.开源.美观.图表丰富.兼容绝大多数浏 ...

  5. [转] Android中的设计模式-备忘录模式

    转自Android中的设计模式-备忘录模式 定义 备忘录设计模式的定义就是把对象的状态记录和管理委托给外界处理,用以维持自己的封闭性. 比较官方的定义 备忘录模式(Memento Pattern)又叫 ...

  6. java中 BeanUtils.copyProperties的用法

    BeanUtils提供了对java发射和自省API的包装,这里对BeanUtils.copyProperties的用法做一个小小的介绍. 通过函数名可以知道,copyProperties函数是对属性进 ...

  7. <基础> PHP 数据类型

    PHP三大数据类型 标量 字符串 单引号:不能解析变量  效率高 双引号 :可以解析变量   效率稍微低一些 heredoc : 大文本 整形 浮点 不能用于比较运算 布尔 复合 数组 超全局数组  ...

  8. ThinkPHP输入验证和I方法使用

    在Web开发过程中,我们经常需要获取系统变量或者用户提交的数据,这些变量数据错综复杂,而且一不小心就容易引起安全隐患,但是如果利用好ThinkPHP提供的变量获取功能,就可以轻松的获取和驾驭变量了. ...

  9. node.js 发送邮件

    var nodemailer = require('nodemailer'); var smtpTransport = require('nodemailer-smtp-transport'); // ...

  10. Python集合的基本操作

    #-*coding:utf-8 -* list =set([2,3,4]) list2 =set([5,3,7]) #交集 #print (list.intersection(list2)) #并集 ...