- 浏览: 124823 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
yingtaier:
[i][4/i]引用-[*]引用---[size=x-larg ...
使用Cxf在中的自定义拦截器来输出日志信息 -
风雨故都:
Page 里面有什么属性
WebService(cxf框架)返回一个包含有map的一个page对象 -
ys20081411:
请问这个乱码和jdk的版本有关系么?我用了你的代码,但是报错了 ...
JSPWiki使用说明书 -
thrillerzw:
哈哈,难啊。
我想找个女朋友,但是不会表白。 -
thrillerzw:
不能 把每带过的地方,只是当成一个路过的地方,从来没有付出过 ...
活在一个有梦想的世界里
举个简单的例子。
给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,第一次出现第几个位置。
这题当然可以用hash来,但是我要介绍的是trie树。在某些方面它的用途更大。比如说对于某一个单词,我要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单。
现在回到例子中,如果我们用最傻的方法,对于每一个单词,我们都要去查找它前面的单词中是否有它。那么这个算法的复杂度就是O(n^2)。显然对于100000的范围难以接受。现在我们换个思路想。假设我要查询的单词是abcd,那么在他前面的单词中,以b,c,d,f之类开头的我显然不必考虑。而只要找以a开头的中是否存在abcd就可以了。同样的,在以a开头中的单词中,我们只要考虑以b作为第二个字母的……这样一个树的模型就渐渐清晰了……
假设有b,abc,abd,bcd,abcd,efg,hii这6个单词,我们构建的树就是这样的。
对于每一个节点,从根遍历到他的过程就是一个单词,如果这个节点被标记为红色,就表示这个单词存在,否则不存在。
那么,对于一个单词,我只要顺着他从根走到对应的节点,再看这个节点是否被标记为红色就可以知道它是否出现过了。把这个节点标记为红色,就相当于插入了这个单词。
我们可以看到,trie树每一层的节点数是26^i级别的。所以为了节省空间。我们用动态链表,或者用数组来模拟动态。空间的花费,不会超过单词数×单词长度。(转自一大牛)
Trie树的java代码 实现如下:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/** *//**
* A word trie which can only deal with 26 alphabeta letters.
* @author Leeclipse
* @since 2007-11-21
*/
public class Trie{
private Vertex root;//一个Trie树有一个根节点
//内部类
protected class Vertex{//节点类
protected int words;
protected int prefixes;
protected Vertex[] edges;//每个节点包含26个子节点(类型为自身)
Vertex() {
words = 0;
prefixes = 0;
edges = new Vertex[26];
for (int i = 0; i < edges.length; i++) {
edges[i] = null;
}
}
}
public Trie () {
root = new Vertex();
}
/** *//**
* List all words in the Trie.
*
* @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 Search words in the Trie and add them to the 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) { //reach the last character of the word
return vertex.prefixes;
}
char c = prefixSegment.charAt(0);
int index = c - 'a';
if (vertex.edges[index] == null) { // the word does NOT exist
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) { //reach the last character of the word
return vertex.words;
}
char c = wordSegment.charAt(0);
int index = c - 'a';
if (vertex.edges[index] == null) { // the word does NOT exist
return 0;
} else {
return countWords(vertex.edges[index], wordSegment.substring(1));
}
}
/** *//**
* Add a word to the Trie.
*
* @param word The word to be added.
*/
public void addWord(String word) {
addWord(root, word);
}
/** *//**
* Add the word from the specified vertex.
* @param vertex The specified vertex.
* @param word The word to be added.
*/
private void addWord(Vertex vertex, String word) {
if (word.length() == 0) { //if all characters of the word has been added
vertex.words ++;
} else {
vertex.prefixes ++;
char c = word.charAt(0);
c = Character.toLowerCase(c);
int index = c - 'a';
if (vertex.edges[index] == null) { //if the edge does NOT exist
vertex.edges[index] = new Vertex();
}
addWord(vertex.edges[index], word.substring(1)); //go the the next character
}
}
public static void main(String args[]) //Just used for test
{
Trie trie = new Trie();
trie.addWord("China");
trie.addWord("China");
trie.addWord("China");
trie.addWord("crawl");
trie.addWord("crime");
trie.addWord("ban");
trie.addWord("China");
trie.addWord("english");
trie.addWord("establish");
trie.addWord("eat");
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 s = (String)listiterator.next();
System.out.println(s);
}
int count = trie.countPrefixes("ch");
int count1=trie.countWords("china");
System.out.println("the count of c prefixes:"+count);
System.out.println("the count of china countWords:"+count1);
}
}
运行:
C:\test>java Trie
10
0
ban
china
crawl
crime
eat
english
establish
the count of c prefixes:4
the count of china countWords:4
文章来自:http://oivoiv.blog.163.com/
给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,第一次出现第几个位置。
这题当然可以用hash来,但是我要介绍的是trie树。在某些方面它的用途更大。比如说对于某一个单词,我要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单。
现在回到例子中,如果我们用最傻的方法,对于每一个单词,我们都要去查找它前面的单词中是否有它。那么这个算法的复杂度就是O(n^2)。显然对于100000的范围难以接受。现在我们换个思路想。假设我要查询的单词是abcd,那么在他前面的单词中,以b,c,d,f之类开头的我显然不必考虑。而只要找以a开头的中是否存在abcd就可以了。同样的,在以a开头中的单词中,我们只要考虑以b作为第二个字母的……这样一个树的模型就渐渐清晰了……
假设有b,abc,abd,bcd,abcd,efg,hii这6个单词,我们构建的树就是这样的。
对于每一个节点,从根遍历到他的过程就是一个单词,如果这个节点被标记为红色,就表示这个单词存在,否则不存在。
那么,对于一个单词,我只要顺着他从根走到对应的节点,再看这个节点是否被标记为红色就可以知道它是否出现过了。把这个节点标记为红色,就相当于插入了这个单词。
我们可以看到,trie树每一层的节点数是26^i级别的。所以为了节省空间。我们用动态链表,或者用数组来模拟动态。空间的花费,不会超过单词数×单词长度。(转自一大牛)
Trie树的java代码 实现如下:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/** *//**
* A word trie which can only deal with 26 alphabeta letters.
* @author Leeclipse
* @since 2007-11-21
*/
public class Trie{
private Vertex root;//一个Trie树有一个根节点
//内部类
protected class Vertex{//节点类
protected int words;
protected int prefixes;
protected Vertex[] edges;//每个节点包含26个子节点(类型为自身)
Vertex() {
words = 0;
prefixes = 0;
edges = new Vertex[26];
for (int i = 0; i < edges.length; i++) {
edges[i] = null;
}
}
}
public Trie () {
root = new Vertex();
}
/** *//**
* List all words in the Trie.
*
* @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 Search words in the Trie and add them to the 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) { //reach the last character of the word
return vertex.prefixes;
}
char c = prefixSegment.charAt(0);
int index = c - 'a';
if (vertex.edges[index] == null) { // the word does NOT exist
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) { //reach the last character of the word
return vertex.words;
}
char c = wordSegment.charAt(0);
int index = c - 'a';
if (vertex.edges[index] == null) { // the word does NOT exist
return 0;
} else {
return countWords(vertex.edges[index], wordSegment.substring(1));
}
}
/** *//**
* Add a word to the Trie.
*
* @param word The word to be added.
*/
public void addWord(String word) {
addWord(root, word);
}
/** *//**
* Add the word from the specified vertex.
* @param vertex The specified vertex.
* @param word The word to be added.
*/
private void addWord(Vertex vertex, String word) {
if (word.length() == 0) { //if all characters of the word has been added
vertex.words ++;
} else {
vertex.prefixes ++;
char c = word.charAt(0);
c = Character.toLowerCase(c);
int index = c - 'a';
if (vertex.edges[index] == null) { //if the edge does NOT exist
vertex.edges[index] = new Vertex();
}
addWord(vertex.edges[index], word.substring(1)); //go the the next character
}
}
public static void main(String args[]) //Just used for test
{
Trie trie = new Trie();
trie.addWord("China");
trie.addWord("China");
trie.addWord("China");
trie.addWord("crawl");
trie.addWord("crime");
trie.addWord("ban");
trie.addWord("China");
trie.addWord("english");
trie.addWord("establish");
trie.addWord("eat");
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 s = (String)listiterator.next();
System.out.println(s);
}
int count = trie.countPrefixes("ch");
int count1=trie.countWords("china");
System.out.println("the count of c prefixes:"+count);
System.out.println("the count of china countWords:"+count1);
}
}
运行:
C:\test>java Trie
10
0
ban
china
crawl
crime
eat
english
establish
the count of c prefixes:4
the count of china countWords:4
文章来自:http://oivoiv.blog.163.com/
发表评论
-
微信公众账号与网站信息对接
2013-07-10 17:37 8827最近做了一个微信 ... -
原子操作实现并发
2012-06-14 17:02 1205使用synchronized: 使用synchroni ... -
velocity配置与springMVC
2012-06-07 11:30 5253web.xml <?xml version=&quo ... -
activiti使用
2011-07-25 15:25 2459使用activiti报错 Caused by: java.l ... -
Struts2请求乱码问题
2011-05-06 16:25 1070ie6中的bug 在jsp请求Action ... -
软件开发流程图
2011-03-25 11:36 1204自己对软件开发流程理解 -
使用AOP实现异常处理
2011-03-16 15:08 5469@Aspect public class Service ... -
使用Freemarker和Struts2做动态表单
2011-03-01 09:49 4865由于项目中需要用到一个可定制的动态表单功能,管理员可以根 ... -
JSPWiki使用说明书
2010-08-31 16:26 7702在使 ... -
jsp 下载出现乱码和空格问题
2010-08-31 13:21 2182关于中文文件下载的问 ... -
代理服务器的缓存问题
2010-06-24 17:00 1199如果要使用代理服务器时,会出现页面信息串。 处理方法(写一个过 ... -
浅谈Eclipse调用Tomcat服务的原理
2010-06-11 14:23 3319转:http://www.173it.cn/Html/?5 ... -
w3c 中doc生成一个基于hibernate的hbm.xml文件
2010-06-03 13:01 1413package com.gosophia.metadata ... -
如何让eclipse辅助提示struts.xml文件的编写
2010-05-21 19:06 2192一般情况下,如果计算机连接上了internet,eclipse ... -
Eclipse 常用设置
2010-05-21 13:40 889转: http://www.blogjava.net/Todd ... -
Java程序执行原理
2010-05-02 17:10 1003<o:p> </o:p>首先 ... -
什么是线程安全
2010-04-30 16:14 925如果你的代码所在 ... -
Servlet的线程安全问题
2010-04-30 15:46 725转:http://zjeers.iteye.com/blog/ ... -
JSR(转)
2010-04-26 13:35 1464J2ME 配置规范 ========= JSR 30 --- ... -
Jpa
2010-04-09 10:20 1958来自:http://www.oracle.com/ ...
相关推荐
在Java中实现Trie树,首先定义节点类`TrieNode`,包括指向26个子节点的数组(表示26个英文字母),字符数据成员`data`,以及词频计数器`freq`。例如: ```java public class TrieNode { public TrieNode[] ...
本项目聚焦于利用Java实现的双数组Trie树,这是一种在字符串处理和搜索中广泛使用的数据结构。 Trie树,又称“前缀树”或“字典树”,是一种用于存储键值对的数据结构,特别适用于字符串。它的主要特点是能以O(1)的...
在Java中实现Trie树,我们需要定义一个TrieNode类,它包含一个字符数组(代表子节点)和一个布尔值(表示当前节点是否为单词的结尾)。我们还需要一个方法来插入字符串到Trie树中,这个过程涉及遍历字符串的每个字符...
基于Java链表实现的字典树(trie),实现了增删改查等功能,它说摘要必须大于50字我还能说啥啥啥啥
总的来说,Java实现的字典树TrieTree是一个强大的工具,尤其适用于处理大量字符串数据,如四六级高频词汇的存储和查询。通过理解和运用这种数据结构,我们可以提高算法效率,优化应用程序的性能。
在Java中实现Trie数据结构,可以帮助我们快速处理大量字符串数据,例如在搜索引擎中进行关键词索引或者在自动补全功能中提供快速建议。 Trie的基本思想是利用字符串的公共前缀来节省存储空间。每个节点代表一个字符...
Prefix Trie数据结构的Java实现。 介绍 尝试是类似于基于有序树的数据结构的地图,可快速搜索O(k)的顺序,其中k是键的长度。 阅读有关trie的更多信息。 动机 它最初是为在我的Android应用程序T9 App Launcher中使用...
DoubleArrayTrie Java编写的DoubleArrayTrie介绍用法// construct and buildDoubleArrayTrie dat = new DoubleArrayTrie(); for(String word: words) { dat.Insert(word); } System.out.println(dat.Base.length); ...
这个实例是用Java语言实现的,我们将深入探讨字典树的工作原理和Java实现的关键点。 首先,字典树的核心概念是利用节点来存储字符串的字符,每个节点可能有多个子节点,对应于下一个可能的字符。根节点通常不包含...
在Java程序中,通常会通过I/O操作读取这些词典文件,并根据其内容构建数据结构,如哈希表或者Trie树,以优化查询效率。 描述中提到的“导入词典”功能存在问题,这可能意味着程序在加载词典时遇到困难,可能是由于...
Trie树可以快速定位到模式串的某个前缀,而失败指针则用于在当前字符不匹配时,快速回溯到可能匹配的下一个位置,无需从根节点重新开始。 在Java中实现AC算法,首先需要创建一个表示Trie节点的数据结构,通常包含...
在这个"trim"压缩包文件中,可能包含了一个用Java实现字典树的项目或代码示例。你可以解压后查看源码,了解如何将上述理论知识应用到实际编程中。同时,学习如何读取文件、构建字典树,以及执行插入、搜索和删除操作...
可能的选择有哈希表(HashMap)、二叉搜索树(如AVL或红黑树)或Trie树(字典树),这些数据结构能快速定位到目标单词并返回翻译。 5. **文件I/O操作**:如果使用文本文件存储词典,那么Java的FileInputStream和...
高效的排序和搜索算法是关键,如Trie树、B树等。 2. **深度学习框架**:可能使用TensorFlow、PyTorch或Deeplearning4j等Java友好的深度学习框架,实现特征提取、模型训练和预测。 3. **自然语言处理(NLP)**:Java ...
本项目是用Java实现的一个敏感词过滤工具,它能对输入的字符串进行检查,并返回其中的敏感词汇。以下是关于这个Java敏感词过滤实现的详细知识讲解。 首先,我们要理解敏感词过滤的基本原理。通常,敏感词过滤系统会...
总结来说,Java实现文章汉字关键词(违禁词)识别需要结合多种数据结构和算法,如哈希表、Trie树、分词库和过滤算法。通过合理的设计和优化,我们可以构建出高效、准确的违禁词检测系统,满足内容审核的需求。
给定算术表达式的DFA图,利用Java语言构建Trie树,实现对输入文法的判断
例如,可以使用Trie树或AC自动机构建索引来加速前缀匹配。 - **启发式算法**:对于复杂问题,可以采用启发式算法,如A*搜索、Beam搜索等,以平衡计算时间和匹配质量。 - **并行计算**:利用Java的并发库,如`java....
#### 二、Trie树的结构与实现 Trie树的基本结构包括以下几点: 1. **节点结构**:每个节点代表一个字符,且通常包含指向子节点的指针数组或哈希表来表示可能的下一个字符。 2. **根节点**:通常不包含任何字符,它...