Implement Trie and find longest prefix string list
package leetcode; import java.util.ArrayList;
import java.util.List; class TrieNode{
Boolean isWord;//true if path till this node represent a string.
Integer freq;//numbers of strings share the same prefix
Character nodeChar;//character for this node
ArrayList<TrieNode> childNodes;
public TrieNode(char c){
childNodes = new ArrayList<TrieNode>();
this.nodeChar = c;
this.freq = 1;
this.isWord = false;
}
public TrieNode(){
childNodes = new ArrayList<TrieNode>();
this.nodeChar = null;
this.freq = 0;
this.isWord = false;
}
} class Prefix{
TrieNode root;
String prefix;
public Prefix(TrieNode root, String s){
this.root = root;
this.prefix = s;
}
} public class Trie {
/*
Trie is an efficient information retrieval data structure.
Using trie, search complexities can be brought to optimal limit (key length).
If we store keys in binary search tree, a well balanced BST will need time proportional to M * log N,
where M is maximum string length and N is number of keys in tree.
Using trie, we can search the key in O(M) time.
However the penalty is on trie storage requirements.
*/
TrieNode root;
public Trie(){
root = new TrieNode();
} public void insert(String s){
if(s == null || s.length() == 0) return;
TrieNode tmp = root;
tmp.freq ++;// prefix freq ++
for(int i = 0; i < s.length(); i ++){
Boolean hasNode = false;
for(int j = 0; j < tmp.childNodes.size(); j ++){
if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
tmp = tmp.childNodes.get(j);
tmp.freq ++;
hasNode = true;
break;
}
}
if(hasNode == false){
TrieNode newNode = new TrieNode(s.charAt(i));
tmp.childNodes.add(newNode);
tmp = newNode;
}
}
tmp.isWord = true;
} public Boolean searchString(String s){
if(s == null || s.length() == 0) return false;
TrieNode tmp = root;
for(int i = 0; i < s.length(); i ++){
Boolean containsChar = false;
for(int j = 0; j < tmp.childNodes.size(); j ++){
if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
tmp = tmp.childNodes.get(j);
containsChar = true;
break;
}
}
if(containsChar == false){
return false;
}
}
return tmp.isWord == true;
} /*
* During delete operation we delete the key in bottom up manner using recursion. The following are possible conditions when deleting key from trie,
* 1. Key may not be there in trie. Delete operation should not modify trie.
* 2. Key present as unique key (no part of key contains another key (prefix), nor the key itself is prefix of another key in trie). Delete all the nodes.
* 3. Key is prefix key of another long key in trie. Unmark the leaf node.
* 4. Key present in trie, having atleast one other key as prefix key. Delete nodes from end of key until first leaf node of longest prefix key.
*/
public void delete(String s){
if(searchString(s) == false) return;
TrieNode tmp = root;
if(tmp.freq == 1){
tmp.childNodes.remove(0);
tmp.freq = 0;
return;
}
for(int i = 0; i < s.length(); i ++){
for(int j = 0; j < tmp.childNodes.size(); j ++){
if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
if(tmp.childNodes.get(j).freq == 1){
tmp.childNodes.remove(j);
tmp.freq --;
return;
}else{
tmp.childNodes.get(j).freq --;
tmp = tmp.childNodes.get(j);
}
break;
}
}
}
tmp.isWord = false; } //find a list of string in the dictionary, which contains the longest prefix with the target string
public List<String> findAllStringWithSameLongestPrefix(String s){
Prefix tmp = findLongestPrefix(s);
List<String> result = new ArrayList<String>();
if(tmp.root.equals(root)) return result;
findAllStringInSubTree(tmp.root, new StringBuilder(tmp.prefix), result);
return result;
} private Prefix findLongestPrefix(String s){
TrieNode tmp = root;
StringBuilder sb = new StringBuilder();
for(int i = 0; i < s.length(); i ++){
Boolean containsChar = false;
for(int j = 0; j < tmp.childNodes.size(); j ++){
if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
sb.append(s.charAt(i));
tmp = tmp.childNodes.get(j);
containsChar = true;
break;
}
}
if(containsChar == false){
return new Prefix(tmp, sb.toString());
}
}
return new Prefix(tmp, s);
} private void findAllStringInSubTree(TrieNode root, StringBuilder sb, List<String> result){
if(root.isWord == true){
result.add(sb.toString());
}
for(int i = 0; i < root.childNodes.size(); i ++){
TrieNode tmp = root.childNodes.get(i);
sb.append(tmp.nodeChar);
findAllStringInSubTree(tmp, new StringBuilder(sb), result);
sb.deleteCharAt(sb.length() - 1);
}
} public static void main(String[] args){
Trie trie = new Trie();
System.out.println("insert string into Trie:");
System.out.println("a, aq, ab, abb, aa, bbd, bd, ba, abc");
trie.insert("a");
trie.insert("aq");
trie.insert("ab");
trie.insert("abb");
trie.insert("aa");
trie.insert("bbd");
trie.insert("bd");
trie.insert("ba");
trie.insert("abc");
System.out.println("search string in Trie:");
System.out.println("abb: " + trie.searchString("abb"));
System.out.println("bd: " + trie.searchString("bd"));
System.out.println("bda: " + trie.searchString("bda"));
System.out.println("strings start with a:");
List<String> list1 = trie.findAllStringWithSameLongestPrefix("a");
for(int i = 0; i < list1.size(); i ++){
System.out.println(list1.get(i));
}
System.out.println("strings start with b:");
List<String> list2 = trie.findAllStringWithSameLongestPrefix("b");
for(int i = 0; list2 != null && i < list2.size(); i ++){
System.out.println(list2.get(i));
}
System.out.println("strings start with ab:");
List<String> list3 = trie.findAllStringWithSameLongestPrefix("ab");
for(int i = 0; i < list3.size(); i ++){
System.out.println(list3.get(i));
}
System.out.println("strings start with abcdef:");
List<String> list4 = trie.findAllStringWithSameLongestPrefix("abcdef");
for(int i = 0; list4 != null && i < list4.size(); i ++){
System.out.println(list4.get(i));
}
System.out.println("delete string from trie:");
trie.delete("ab");
System.out.println(trie.searchString("ab"));
System.out.println(trie.searchString("abb"));
}
}
Output:
insert string into Trie:
a, aq, ab, abb, aa, bbd, bd, ba, abc
search string in Trie:
abb: true
bd: true
bda: false
strings start with a:
a
aq
ab
abb
abc
aa
strings start with b:
bbd
bd
ba
strings start with ab:
ab
abb
abc
strings start with abcdef:
abc
delete string from trie:
false
true
Implement Trie and find longest prefix string list的更多相关文章
- Leetcode: Implement Trie (Prefix Tree) && Summary: Trie
Implement a trie with insert, search, and startsWith methods. Note: You may assume that all inputs a ...
- leetcode面试准备:Implement Trie (Prefix Tree)
leetcode面试准备:Implement Trie (Prefix Tree) 1 题目 Implement a trie withinsert, search, and startsWith m ...
- Implement Trie (Prefix Tree) 解答
Question Implement a trie with insert, search, and startsWith methods. Note:You may assume that all ...
- [Swift]LeetCode208. 实现 Trie (前缀树) | Implement Trie (Prefix Tree)
Implement a trie with insert, search, and startsWith methods. Example: Trie trie = new Trie(); trie. ...
- 【LeetCode】208. Implement Trie (Prefix Tree)
Implement Trie (Prefix Tree) Implement a trie with insert, search, and startsWith methods. Note:You ...
- [LeetCode] 208. Implement Trie (Prefix Tree) ☆☆☆
Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...
- 字典树(查找树) leetcode 208. Implement Trie (Prefix Tree) 、211. Add and Search Word - Data structure design
字典树(查找树) 26个分支作用:检测字符串是否在这个字典里面插入.查找 字典树与哈希表的对比:时间复杂度:以字符来看:O(N).O(N) 以字符串来看:O(1).O(1)空间复杂度:字典树远远小于哈 ...
- LeetCode208 Implement Trie (Prefix Tree). LeetCode211 Add and Search Word - Data structure design
字典树(Trie树相关) 208. Implement Trie (Prefix Tree) Implement a trie with insert, search, and startsWith ...
- 【刷题-LeetCode】208. Implement Trie (Prefix Tree)
Implement Trie (Prefix Tree) Implement a trie with insert, search, and startsWith methods. Example: ...
随机推荐
- CSS过渡动画之transition
O(∩_∩)O~ 这两天在看看CSS的相关内容,关于transition动画感觉很有意思,分享一下. CSS负责给html加效果,自然少不了各种动画,今天介绍一下transition. 概述 看一段比 ...
- 3.PO如何给开发团队讲好故事
敏捷开发系列文章目录 讲出符合开发团队味口的故事. 上一章说了敏捷开发团队的构成与迭代过程,本章重点说一下迭代第一天的计划会议.熟话说“好的开始就成功了一半”,一个迭代的计划会议做得好不好确实直接注定 ...
- jmeter汉化
测试需要许多工具辅助工作,我们在使用这些工具之前需要对工具有一定的了解,第一步就是需要安装特定的软件. 因为工具基本上都是英文版的,所以菜鸟使用就面临汉化的问题,下面介绍几种汉化的办法: 一.万事不决 ...
- 接口测试中抓包工具Charles的使用
在被测接口并没有明确的接口文档给出时,我们需要借助抓包工具来帮助测试,利用抓包工具我们几乎可以获得接口文档中能给你的一切.常见的抓包工具有Charles和Fiddler, Fiddler只能用在Win ...
- Python-RabbitMQ(持久化)
生产者: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import pika connection = pika.BlockingConnection(pi ...
- 别再犯低级错误,带你了解更新缓存的四种Desigh Pattern
在我们使用分布式缓存Redis或者Memcached编写更新缓存数据代码时,我们总是会犯一个逻辑错误.先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中.试想,两个并发操作,一个是更新操 ...
- docker入门使用教程
Docker概念 Docker是开发人员和系统管理员 使用容器开发,部署和运行应用程序的平台.使用Linux容器部署应用程序称为容器化.容器不是新的,但它们用于轻松部署应用程序. 容器化越来越受欢迎, ...
- 笔试题——C++后序字符比较
题目:从两个数组的最后一个元素开始比较,输出数组中不同元素的个数.当一个数组的所有元素比较完成后,结束比较.a数组长度5,b数组长度3,a[ 4 ]和b[ 2 ]比较. 例: 输入: 77 21 1 ...
- dvwa——sql手动注入和sqlmap自动注入
手动注入 low: 源码: <?php if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; ...
- export命令详解
基础命令学习目录首页 export 的基本作用就是将父shell中的局部变量设置为环境变量,使得该变量可以在子shell中使用.下面设置两种情景对export进行原理解析. 情景 1. 有一个名为m ...