`

Trie tree(字典树)的Java实现及其应用-统计以某字符串为前缀的单词的数量

 
阅读更多
import java.util.LinkedList;

public class CaseInsensitiveTrie {

	/**
	字典树的Java实现。实现了插入、查询以及深度优先遍历。 
    Trie tree's java implementation.(Insert,Search,DFS)
    
	Problem Description
	Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).

	Input
	输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
	注意:本题只有一组测试数据,处理到文件结束.

	Output
	对于每个提问,给出以该字符串为前缀的单词的数量.

	Sample Input
	banana
	band
	bee
	absolute
	acm

	ba
	b
	band
	abc
	 
	Sample Output
	2
	3
	1
	0
	*/
	private int SIZE = 26;// 26 letters.CaseInsensitive.
	private TrieNode root;

	CaseInsensitiveTrie() {
		root = new TrieNode();
	}

	private class TrieNode {
		private int num;// how many words go through this node.
		private TrieNode[] son;// TrieNode[26] in this case
		private boolean isEnd;// end of a string.
		private char val;// No this field mostly.
		// But I think it's easy to traverse when having a specific value in
		// each node.
		private boolean visited;// add this field for DFS

		TrieNode() {
			num = 1;//num=0 is wrong
			son = new TrieNode[SIZE];
			isEnd = false;
			visited = false;
		}
	}

	public void insert(String str) {
		if (str == null || str.length() == 0) {
			return;
		}
		TrieNode node = root;
		char[] letters=str.toCharArray();
		for (int i = 0, len = str.length(); i < len; i++) {
			int pos = letters[i] - 'a';
			if (node.son[pos] == null) {
				node.son[pos] = new TrieNode();
				node.son[pos].val = letters[i];
			} else {
				node.son[pos].num++;//for 'countPrefix(String prefix)'
			}
			node = node.son[pos];
		}
		node.isEnd = true;
	}

	/**
	 * count how many words start with the specific prefix.
	 * since we count it in insertion,what we need to do is to return the 'num' of the last letter of prefix.
	 */
	public int countPrefix(String prefix){
		if(prefix==null||prefix.length()==0){
			return -1;
		}
		TrieNode node=root;
		char[] letters=prefix.toCharArray();
		for(int i=0,len=prefix.length();i<len;i++){
			int pos=letters[i]-'a';
			if(node.son[pos]==null){
				return 0;
			}else{
				node=node.son[pos];
			}
		}
		return node.num;
	}
	
	// search a word in the tree.Complete matching.
	public boolean has(String str) {
		if (str == null || str.length() == 0) {
			return false;
		}
		TrieNode node = root;
		char[] letters=str.toCharArray();
		for (int i = 0, len = str.length(); i < len; i++) {
			int pos = letters[i] - 'a';
			if (node.son[pos] != null) {
				node = node.son[pos];
			} else {
				return false;
			}
		}
		return node.isEnd;
	}

	// DFS.Use stack.Like a 26-nary tree.
	public void printAllWords() {
		TrieNode rootNode = root;
		if (root == null){
			return;
		}
		LinkedList<TrieNode> list = new LinkedList<TrieNode>();
		for (int i = 0; i < SIZE; i++) {
			TrieNode node = rootNode.son[i];
			if (node != null) {
				list.addLast(node);
				while (!list.isEmpty()) {
					TrieNode curNode = list.getLast();
					TrieNode firstChild = firstChildOf(curNode);
					while (firstChild != null) {
						list.addLast(firstChild);
						firstChild = firstChildOf(firstChild);// DFS.
					}
					TrieNode strEnd = list.getLast();
					if (strEnd.isEnd) {
						printLinkedList(list);
					}
					list.removeLast();
				}
			}
			list.clear();
		}
	}

	//print each node in preOrder.
	public void preTraverse(TrieNode node){
		if(node!=null){
			System.out.print(node.val+"-");
			for(TrieNode child:node.son){
				preTraverse(child);
			}
		}
		
	}
	// get the first unvisited child of a node.
	public TrieNode firstChildOf(TrieNode node) {
		if (node == null)
			return null;
		for (int i = 0; i < SIZE; i++) {
			TrieNode tmp = node.son[i];
			if (tmp != null && !tmp.visited) {
				tmp.visited = true;
				return tmp;
			}
		}
		return null;
	}

	public static void printLinkedList(LinkedList<TrieNode> list) {
		if (list == null || list.size() == 0){
			return;
		}
		StringBuilder sb = new StringBuilder();
		for (int i = 0, len = list.size(); i < len; i++) {
			sb.append(list.get(i).val);
		}
		System.out.println(sb.toString());
	}

	public TrieNode getRoot(){
		return this.root;
	}
	
	public static void main(String[] args) {
		CaseInsensitiveTrie tree = new CaseInsensitiveTrie();
		String[] strs={
				"banana",
				"band",
				"bee",
				"absolute",
				"acm",
		};
		String[] prefix={
			"ba",
			"b",
			"band",
			"abc",
		};
		for(String str:strs){
			tree.insert(str);
		}
		System.out.println(tree.has("abc"));
		tree.preTraverse(tree.getRoot());
		System.out.println();
		tree.printAllWords();
		for(String pre:prefix){
			int num=tree.countPrefix(pre);
			System.out.println(pre+" "+num);
		}
		
	}
}



另一道类似的题目:
Description
Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers:
Emergency 911
Alice 97 625 999
Bob 91 12 54 26
In this case, it's not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob's phone number. So this list would not be consistent.
Input
The first line of input gives a single integer, 1 ≤ t ≤ 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 ≤ n ≤ 10000. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.
Output
For each test case, output "YES" if the list is consistent, or "NO" otherwise.
Sample Input
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
Sample Output
NO
YES

这道题用TrieTree也好做:在插入某个号码时候,如果遇到一个节点已经isEnd==true而号码还没有插入完成,则返回NO
0
0
分享到:
评论
1 楼 neyshule 2012-09-04  
不错啊,有没有删除的代码啊。

相关推荐

    Java实现字典树TrieTree

    在计算机科学中,字典树(也称为前缀树或TrieTree)是一种高效的数据结构,主要用于存储字符串集合。它能够快速地进行关键词查找、插入和删除操作,尤其适合于处理大量的词汇数据,如在四六级英语考试的高频词汇查询...

    Go-trie-单词查找树实现Go实现

    在实际应用中,Trie常用于搜索引擎、自动补全、IP路由表等场景,它能快速地找到所有以特定前缀开头的字符串。通过压缩包子文件`trie-master`,我们可以进一步学习和研究这个Go实现的Trie数据结构,包括可能包含的...

    Trie树(字典树)的介绍及Java实现

    Trie树,也被称为字典树或前缀树,是一种数据结构,主要用于高效地存储和检索字符串集合中的数据。在Trie树中,每个节点代表一个字符串的前缀,从根节点到某个节点的路径上的字符序列构成了该节点对应的字符串。这种...

    HASH(Trie)-.rar_HashTree.h_TRIE_hash树_trie树_字典树

    Trie,又被称为前缀树或字典树,是一种用于存储键值对的数据结构,尤其适用于字符串的查找和管理。 **Trie 树基础知识** Trie 树是一种多叉树,每个节点代表一个字符串的前缀。根节点不包含任何字符,而叶子节点则...

    Trie 字典树 Objective-c 算法实现

    Trie,也被称为“前缀树”或“字典树”,是一种用于存储字符串的数据结构,它在计算机科学中常被用于高效地执行字符串查找操作。在Objective-C中实现Trie算法,可以帮助开发者快速处理大量字符串数据,例如在搜索...

    11 TrieTree.rar

    在众多的数据结构中,TrieTree(又称前缀树或字典树)是一种高效且具有广泛应用场景的结构。本篇将深入探讨TrieTree的基本概念、构造方法以及在实际中的应用。 一、TrieTree概述 TrieTree是一种基于字符串的查找...

    【ASP.NET编程知识】TrieTree服务-组件构成及其作用介绍.docx

    TrieTree,又称字典树或前缀树,它允许快速查找具有相同前缀的字符串,常用于搜索引擎和自动补全功能。下面将详细介绍TrieTree服务的组件构成及其作用。 1. **Dictionary组件**: Dictionary组件是TrieTree服务的...

    字典树php实现

    字典树,也称为前缀树或Trie树,是一种用于存储字符串数据结构,它能够高效地支持诸如查找、插入和删除等操作。由于其在字符串处理上的独特优势,字典树被广泛应用于诸多领域,如文本编辑器的自动补全功能、搜索引擎...

    PHP-TrieTree-master.zip

    【PHP-TrieTree-master.zip】是一个包含PHP实现的字典树(Trie Tree)数据结构的资源包。这个项目由AbelZhou在GitHub上开源,提供了完整的代码库供开发者学习和使用。字典树是一种高效的数据结构,常用于字符串搜索...

    Trie树 结构描述 实现方法 用法

    Trie树,也被称为前缀树或字典树,是一种数据结构,主要用于高效地存储和检索字符串。在Trie树中,每个节点代表一个字符串的前缀,而从根节点到某个节点的路径上的边代表了这个节点所代表的字符串。这种结构特别适合...

    11 TrieTree.zip

    本资料包"11 TrieTree.zip"专注于一个特定的数据结构——Trie(也称为前缀树或字典树),这是在文本处理、搜索引擎优化以及许多其他领域中广泛应用的一种高效工具。TrieTree是由著名计算机科学家严蔚敏教授在《数据...

    字典树求公共前缀字符串数目

    字典树求具有公共前缀的字符串数目, 对应的博客地址:http://blog.csdn.net/ns_code/article/details/21183495

    POJ2525-Text Formalization【TrieTree】

    今天我们要探讨的是一个名为"POJ2525-Text Formalization"的问题,它涉及到一种高效的数据结构——Trie树(也称为前缀树或字典树)。这个题目来源于北京大学的在线判题系统POJ,旨在考察程序员对字符串处理和Trie树...

    字典树_英汉词典

    ### 字典树(Trie Tree)相关知识点 #### 一、什么是字典树? 字典树,也称为前缀树或Trie树,是一种用于存储字符串的高效数据结构。它利用了字符串之间的公共前缀来减少存储空间的需求,并且能够快速进行插入、...

    详解字典树Trie结构及其Python代码实现

    字典树,也称为Trie,是一种特殊的树形数据结构,主要用于快速查找和统计具有公共前缀的字符串。这种数据结构在处理大量字符串时特别有用,例如在搜索引擎的文本词频统计、搜索建议和拼写检查等场景中。Trie的主要...

    字典树应用,检索文本文件单词

    字典树,也被称为Trie或Prefix Tree,是一种用于存储字符串的数据结构,它在IT领域尤其是在文本处理、搜索引擎和编程语言实现中具有广泛的应用。字典树的主要特点是能够快速进行字符串的查找、插入和删除操作,尤其...

    DT_字典树前缀推荐_源码

    在IT领域,字典树(Trie,也称为Prefix Tree或Patricia Tree)是一种非常重要的数据结构,尤其在实现高效前缀匹配和推荐系统时。本文将深入探讨字典树的概念、工作原理以及如何利用它来实现“前缀推荐”功能。 首先...

    AhoCorasickAutomation.rar_字符串字典_有限状态自动机

    Aho-Corasick 算法便是为此目的而设计的一种高级搜索策略,它巧妙地结合了字典树(Trie Tree)和有限状态自动机(Finite State Automaton, FSA)的概念,极大地提升了字符串匹配的效率。 Aho-Corasick 算法由艾兹格...

    leetcode卡-TrieTree:前缀树

    前缀树,也被称为Trie树或字典树,是一种用于存储字符串的数据结构,它能够高效地进行前缀匹配查询。在LeetCode中,前缀树是解决一系列问题的关键工具,尤其是在处理字符串相关的搜索和过滤任务时。在这个“TrieTree...

Global site tag (gtag.js) - Google Analytics