package com.shundong.utils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; /**
* 一个只能处理26个字母的单词树(trie)
* 空间换时间 T(n) = O(n)
* ps:如果缺陷 欢迎留言
* @author shundong
* @data 2018-10-13
*/ public class FindWordsTrie{
//一个Trie树有一个根节点
private Vertex root; //内部类or节点类
protected class Vertex{
protected int words;
protected int prefixes;
//每个节点包含26个子节点(类型为自身)
protected Vertex[] edges;
Vertex() {
words = 0;
prefixes = 0;
edges = new Vertex[26];
for (int i = 0; i < edges.length; i++) {
edges[i] = null;
}
}
} public FindWordsTrie () {
root = new Vertex();
} /**
* 列出List所有单词
* @return
*/
public List< String> listAllWords() { List< String> words = new ArrayList< String>();
Vertex[] edges = root.edges; for (int i = 0; i < edges.length; i++) {
if (edges[i] != null) {
String word = "" + (char)('a' + i);
depthFirstSearchWords(words, edges[i], word);
}
}
return words;
} /**
* Depth First在Trie中搜索单词并将它们添加到List中。
* @param words
* @param vertex
* @param wordSegment
*/
private void depthFirstSearchWords(List words, Vertex vertex, String wordSegment) {
Vertex[] edges = vertex.edges;
boolean hasChildren = false;
for (int i = 0; i < edges.length; i++) {
if (edges[i] != null) {
hasChildren = true;
String newWord = wordSegment + (char)('a' + i);
depthFirstSearchWords(words, edges[i], newWord);
}
}
if (!hasChildren) {
words.add(wordSegment);
}
} public int countPrefixes(String prefix) {
return countPrefixes(root, prefix);
} private int countPrefixes(Vertex vertex, String prefixSegment) {
if (prefixSegment.length() == 0) { //到达单词的最后一个字符
return vertex.prefixes;
}
char c = prefixSegment.charAt(0);
int index = c - 'a';
if (vertex.edges[index] == null) { // 这个词不存在
return 0;
} else {
return countPrefixes(vertex.edges[index], prefixSegment.substring(1));
}
} public int countWords(String word) {
return countWords(root, word);
} private int countWords(Vertex vertex, String wordSegment) {
if (wordSegment.length() == 0) { //到达单词的最后一个字符
return vertex.words;
}
char c = wordSegment.charAt(0);
int index = c - 'a';
if (vertex.edges[index] == null) { // 这个词不存在
return 0;
} else {
return countWords(vertex.edges[index], wordSegment.substring(1));
} }
/**
* 在Trie上添加一个单词
* @param word 要添加的词
*/
public void addWord(String word) {
addWord(root, word);
}
/**
* 添加指定顶点的单词
* @param vertex 指定的顶点
* @param word 要添加的词
*/
private void addWord(Vertex vertex, String word) {
if (word.length() == 0) { //如果已添加该单词的所有字符
vertex.words ++;
} else {
vertex.prefixes ++;
char c = word.charAt(0);
c = Character.toLowerCase(c);
int index = c - 'a';
if (vertex.edges[index] == null) { //如果边缘不存在
vertex.edges[index] = new Vertex();
}
addWord(vertex.edges[index], word.substring(1)); //去下一个
}
}
//简单的测试测试
public static void main(String args[])
{
FindWordsTrie trie = new FindWordsTrie();
trie.addWord("cabbage");
trie.addWord("cabbage");
trie.addWord("cabbage");
trie.addWord("cabbage");
trie.addWord("cabin");
trie.addWord("berte");
trie.addWord("cabbage");
trie.addWord("english");
trie.addWord("establish");
trie.addWord("good"); // System.out.println(trie.root.prefixes);
// System.out.println(trie.root.words);
// List< String> list = trie.listAllWords();
// Iterator listiterator = list.listIterator();
// //遍历
// while(listiterator.hasNext())
// {
// String str = (String)listiterator.next();
// System.out.println(str);
// }
int count = trie.countPrefixes("c");//此处传参
int count1=trie.countWords("cabbage");
System.err.println("单词c 前缀个数为:"+count);
System.err.println("cabbage 单词的个数为:"+count1);
}
}

  

Java实现单词树(trie)的更多相关文章

  1. Java数据结构——字典树TRIE

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

  2. K:单词查找树(Trie)

      单词查找树,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串.Trie可以看作是一个确定有限状态自动机(DFA).与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中 ...

  3. 字典树(Trie树)的实现及应用

    >>字典树的概念 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树.与二叉查找树不同,Trie树的 ...

  4. Atitit 常见的树形结构 红黑树  二叉树   B树 B+树  Trie树 attilax理解与总结

    Atitit 常见的树形结构 红黑树  二叉树   B树 B+树  Trie树 attilax理解与总结 1.1. 树形结构-- 一对多的关系1 1.2. 树的相关术语: 1 1.3. 常见的树形结构 ...

  5. 字典树trie的学习与练习题

    博客详解: http://www.cnblogs.com/huangxincheng/archive/2012/11/25/2788268.html http://eriol.iteye.com/bl ...

  6. 『字典树 trie』

    字典树 (trie) 字典树,又名\(trie\)树,是一种用于实现字符串快速检索的树形数据结构.核心思想为利用若干字符串的公共前缀来节约储存空间以及实现快速检索. \(trie\)树可以在\(O(( ...

  7. 字典树trie学习

    字典树trie的思想就是利用节点来记录单词,这样重复的单词可以很快速统计,单词也可以快速的索引.缺点是内存消耗大 http://blog.csdn.net/chenleixing/article/de ...

  8. 字典树Trie的使用

    1. Trie树介绍 Trie,又称单词查找树.前缀树,是一种多叉树结构.如下图所示: 上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, ...

  9. 字典树(Trie)详解

    详解字典树(Trie) 本篇随笔简单讲解一下信息学奥林匹克竞赛中的较为常用的数据结构--字典树.字典树也叫Trie树.前缀树.顾名思义,它是一种针对字符串进行维护的数据结构.并且,它的用途超级广泛.建 ...

随机推荐

  1. [代码]--给任意网站添加聊天功能,随时聊(fa)天(che)

    感谢“topurl.cn”制作此功能并分享. 这是一段代码,在打开的网页中使用,可以加载一个外挂形式的聊天室功能, 就可以和同样访问此网站进行相同操作的网友进行聊(fa)天(che)了. 使用方法: ...

  2. python字典与集合操作

    字典操作 字典一种key - value 的数据类型,使用就像我们上学用的字典,通过笔划.字母来查对应页的详细内容. 语法: info = { 's1': "jack", 's3' ...

  3. Codeforces715 B. Complete The Graph

    传送门:>Here< 题意:给出一张带权无向图,其中有一些边权为0.要求将边权为0的边的边权重置为一个任意的正整数,使得从S到T的最短路为L.判断是否存在这种方案,如果存在输出任意一种 解 ...

  4. 【HDU 4343】Interval query(倍增)

    BUPT2017 wintertraining(15) #8D 题意 给你x轴上的N个线段,M次查询,每次问你[l,r]区间里最多有多少个不相交的线段.(0<N, M<=100000) 限 ...

  5. Codeforces Round #545 Div1 题解

    Codeforces Round #545 Div1 题解 来写题解啦QwQ 本来想上红的,结果没做出D.... A. Skyscrapers CF1137A 题意 给定一个\(n*m\)的网格,每个 ...

  6. <Android基础>(二) Activity Part 2

    1.活动生命周期 1)返回栈 2)活动状态 3)活动的生存期 2.活动的启动模式 1)standard 2)singleTop 3)singleTask 4)singleInstance 3.活动的优 ...

  7. unittest单元测试框架中的参数化及每个用例的注释

    相信大家和我有相同的经历,在写自动化用例脚本的时候,用例的操作是一样的,但是就是参数不同,比如说要测一个付款的接口,付款有很多种渠道,另外只有部分参数不一样,如果我们一个渠道一个渠道的写,在unitt ...

  8. 两数之和 II - 输入有序数组

    题目描述 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返 ...

  9. 51Nod--1076 2条不相交的路径(强连通分量)

    电波 #include<bits/stdc++.h> using namespace std; #define LL long long #define maxn 30000 vector ...

  10. 编写高质量代码:改善Java程序的151个建议 --[65~78]

    编写高质量代码:改善Java程序的151个建议 --[65~78] 原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱. public class Client65 { public ...