1、Trie树

Trie树即字典树或前缀树,

2、实践

代码实践如下:

 package cn.edu.buaa.trie;

 import java.util.HashSet;

 /**
* @author zsm
* @date 2016年10月25日 上午11:03:13
* @version 1.0
* @parameter
* @return
*/
public class Trie {
private TrieNode trieRoot;
private int treeSize; public Trie() {
trieRoot = new TrieNode();
treeSize = 0;
} public TrieNode getRoot() {
return trieRoot;
} public int getTreeSize() {
return treeSize;
} /**
* 添加单词
*/
public void addWord(String word, int wordId) {
addWord(trieRoot, word, wordId);
} public void addWord(TrieNode root, String word, int wordId) {
// 输入单词为空
if (null == word || word.length() == 0) {
return;
} // 确定第一个字符在放在哪个孩子节点中
int k = TrieNode.getCharPosition(word.charAt(0)); // 该孩子为空,初始化
if (root.childNodes[k] == null) {
root.childNodes[k] = new TrieNode();
treeSize++;
root.childNodes[k].nodeChar = word.charAt(0);
}
// 单词出现在该孩子节点中
root.childNodes[k].wordSet.add(wordId); word = word.substring(1);
// 说明是最后一个字符,该词词频数加1
if (word.length() == 0) {
root.childNodes[k].freq++;
} else {
addWord(root.childNodes[k], word, wordId);
}
} /**
* 删除单词
*/
public void deleteWord(String word, int wordId) {
deleteWord(trieRoot, word, wordId);
} enum DELETERES {
FAIL_EMPTYWORLD, FAIL_WORLD_NOT_EXIST, SUCCESS
}; public DELETERES deleteWord(TrieNode root, String word, int wordId) {
// 输入单词为空
if (null == word || word.length() == 0) {
return DELETERES.FAIL_EMPTYWORLD;
} int k = TrieNode.getCharPosition(word.charAt(0)); // 第一个字符不在树中,说明没有要删除的单词
if (root.childNodes[k] == null) {
return DELETERES.FAIL_WORLD_NOT_EXIST;
} // 第一个字符在树中
DELETERES res;
{
word = word.substring(1);
// 找到该单词
if (word.length() == 0 && root.childNodes[k].freq > 0) {
root.childNodes[k].freq--;
res = DELETERES.SUCCESS;
} else {
res = deleteWord(root.childNodes[k], word, wordId);
} if (res == DELETERES.SUCCESS) {
// 从沿途节点移除该单词
root.childNodes[k].wordSet.remove(wordId);
// 没单词了,释放节点
if (root.childNodes[k].wordSet.size() == 0) {
root.childNodes[k] = null;
treeSize--;
}
}
return res;
}
} /**
* 修改单词
*/
public void updateWord(String newWord, String oldWord, int wordId) {
updateWord(trieRoot, newWord, oldWord, wordId);
} public void updateWord(TrieNode root, String newWord, String oldWord, int wordId) {
if (deleteWord(root, oldWord, wordId) == DELETERES.SUCCESS) {
addWord(root, newWord, wordId);
}
} /**
* 找以给定单词为前缀的所有单词的id
*/
public HashSet<Integer> searchPrefixWord(String word) {
return searchPrefixWord(trieRoot, word);
} public HashSet<Integer> searchPrefixWord(TrieNode root, String word) { HashSet<Integer> wordSet = new HashSet<Integer>(); // 输入单词为空
if (null == word || word.length() == 0) {
return wordSet;
} int k = TrieNode.getCharPosition(word.charAt(0));
// 单词里某个字符在树种不存在,说明没有该单词
if (root.childNodes[k] == null) {
return wordSet;
} word = word.substring(1); if (word.length() == 0) {
wordSet = root.childNodes[k].wordSet;
} else {
wordSet = searchPrefixWord(root.childNodes[k], word);
}
return wordSet;
} /**
* 统计给定单词出现的次数
*/
public int wordCount(String word) {
return wordCount(trieRoot, word);
} public int wordCount(TrieNode root, String word) { // 输入单词为空
if (null == word || word.length() == 0) {
return 0;
} int k = TrieNode.getCharPosition(word.charAt(0));
// 单词里某个字符在树种不存在,说明没有该单词
if (root.childNodes[k] == null) {
return 0;
} int count = 0;
word = word.substring(1); if (word.length() == 0) {
count = root.childNodes[k].freq;
} else {
count = wordCount(root.childNodes[k], word);
} return count;
}
} /**
* Trie树的节点<br>
* 假定单词都由26个英文字母组成,Trie树根节点不存字符
*/
class TrieNode {
// 孩子节点
public TrieNode[] childNodes;
// 该节点的字符
public char nodeChar; // 以该节点为结束的单词的词频
public int freq;
// 包含该节点的单词的id
public HashSet<Integer> wordSet; // 初始化
public TrieNode() {
childNodes = new TrieNode[CHILD_NUM];
freq = 0;
wordSet = new HashSet<Integer>();
} private static final int CHILD_NUM = 26; public static int getCharPosition(char ch) {
return (ch - 'a');
}
}

测试:

 package cn.edu.buaa.trie;

 /**
* @author zsm
* @date 2016年10月25日 下午3:12:02
* @version 1.0
* @parameter
* @return
*/
public class Main_Trie { public static void main(String[] args) {
// TODO Auto-generated method stub
Trie trie = new Trie();
String wd1 = "ab";
String wd2 = "ac";
String wd3 = "acd"; String wd4 = "add"; trie.addWord(wd1, 1);
trie.addWord(wd2, 2);
trie.addWord(wd2, 3);
trie.addWord(wd3, 4); // wd1,wd2,wd2,wd3
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.deleteWord(wd3, 4);
// wd1,wd2,wd2
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.addWord(wd3, 4);
// wd1,wd2,wd2,wd3
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.deleteWord(wd2, 2);
trie.deleteWord(wd2, 3);
// wd1,wd3
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(trie.searchPrefixWord("a"));// [1,4]
System.out.println(); trie.updateWord(wd3, wd4, 4);
// wd1,wd3
System.out.println(trie.searchPrefixWord("a"));// [1,4]
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.wordCount(wd4));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.updateWord(wd4, wd3, 4);
// wd1,wd4
System.out.println(trie.searchPrefixWord("a"));// [1,4]
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.wordCount(wd4));//
System.out.println(trie.getTreeSize());//
System.out.println();
}
}

3、参考资料

http://www.cnblogs.com/huangxincheng/archive/2012/11/25/2788268.html

Trie tree实践的更多相关文章

  1. 字典树(Trie Tree)

    终于要开始更新我的ACM学习之路了,不过没想到却是因为一次Java大作业,有趣,%yuan老师. 字典树是一种很简单的树形结构,主要用来进行词频统计,在算法竞赛中有时也会碰到. 字典树的基本思路是,通 ...

  2. 关于Trie Tree简单实现

    最近突然有兴致hiho一下了,实现了下trie tree,感觉而言,还是挺有意思的,个人觉得这货不光可以用来查单词吧,其实也可以用来替代Hash,反正查找,插入复杂度都挺低的,哈哈,啥都不懂,瞎扯.. ...

  3. 笔试算法题(39):Trie树(Trie Tree or Prefix Tree)

    议题:TRIE树 (Trie Tree or Prefix Tree): 分析: 又称字典树或者前缀树,一种用于快速检索的多叉树结构:英文字母的Trie树为26叉树,数字的Trie树为10叉树:All ...

  4. Phone List POJ 3630 Trie Tree 字典树

    Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29416   Accepted: 8774 Descr ...

  5. 字典树(Trie Tree)

    在图示中,键标注在节点中,值标注在节点之下.每一个完整的英文单词对应一个特定的整数.Trie 可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的.键不需要被显式地保存在节点中. ...

  6. hdu3724Encoded Barcodes(Trie tree)

    题目请戳这里 题目大意:给n个字符串,给m个询问,每个询问给k个条形码.每个条形码由8个小码组成,每个小码有相应的宽度,已知一个条形码的宽度只有2种,宽的表示1,窄的表示0.并且宽的宽度是窄的宽度的2 ...

  7. trie tree(字典树)

    hihocoder题目(http://hihocoder.com/problemset):#1014 trie树 #include <iostream> using namespace s ...

  8. Find the Clones Trie Tree

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8306   Accepted: 3130 Description Doubl ...

  9. 字典树Trie Tree

    又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用字符串的公共前缀 ...

随机推荐

  1. Ubuntu上通过nginx部署Django笔记

    Django的部署可以有很多方式,采用nginx+uwsgi的方式是其中比较常见的一种方式.今天在Ubuntu上使用Nginx部署Django服务,虽然不是第一次搞这个了,但是发现还是跳进了好多坑,g ...

  2. 【推荐】CentOS安装vsftpd-3.0.2+安全配置

    注:以下所有操作均在CentOS 6.5 x86_64位系统下完成. FTP的登录一般有三种方式,分别是: 匿名用户形式:默认安装的情况下,系统只提供匿名用户访问,只需要输入用户anonymous/f ...

  3. Apache 安装配置详情

    本次文章讲解Apache的安装和基本的配置 输入PHP环境搭建的一部分 PHP完整配置信息请参考 http://www.cnblogs.com/azhe-style/p/php_new_env_bui ...

  4. SQL SERVER 2014 各个版本支持的功能

    转自:https://technet.microsoft.com/library/cc645993 转换箱规模限制 功能名称 Enterprise Business Intelligence Stan ...

  5. openstack 命令行管理 - 目录

    原文http://blog.csdn.net/signmem/article/details/19513775 相关 openstack  命令行管理, 分下面部分进行介绍 openstack 命令行 ...

  6. ElasticSearch集群设置

    多台机器 \config\elasticsearch.yml 文件修改 cluster.name设置统一的集群名如 cluster.name: win-es-001 node.name 设置当前Nod ...

  7. 2016.10.29 NOIP模拟赛 PM 考试整理

    300分的题,只得了第三题的100分. 题目+数据:链接:http://pan.baidu.com/s/1o7P4YXs 密码:4how T1:这道题目存在着诸多的问题: 1.开始的序列是无法消除的( ...

  8. Oracle基本数据类型

    一 字符串类型 字符串数据类型还可以依据存储空间分为固定长度类型(CHAR/NCHAR) 和可变长度类型(VARCHAR2/NVARCHAR2)两种. 所谓固定长度:是指虽然输入的字段值小于该字段的限 ...

  9. java之多线程 一

    概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程与线程: 进程是指处于运 ...

  10. MVC 问答

    1.View含有什么,默认就念有Models吗? 不是,ViewBag是一个空对象.ViewBag 与 Models 不是必须一起使用的 . 2.Models 可用可不用?存在意义?