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的更多相关文章

  1. Leetcode: Implement Trie (Prefix Tree) && Summary: Trie

    Implement a trie with insert, search, and startsWith methods. Note: You may assume that all inputs a ...

  2. leetcode面试准备:Implement Trie (Prefix Tree)

    leetcode面试准备:Implement Trie (Prefix Tree) 1 题目 Implement a trie withinsert, search, and startsWith m ...

  3. Implement Trie (Prefix Tree) 解答

    Question Implement a trie with insert, search, and startsWith methods. Note:You may assume that all ...

  4. [Swift]LeetCode208. 实现 Trie (前缀树) | Implement Trie (Prefix Tree)

    Implement a trie with insert, search, and startsWith methods. Example: Trie trie = new Trie(); trie. ...

  5. 【LeetCode】208. Implement Trie (Prefix Tree)

    Implement Trie (Prefix Tree) Implement a trie with insert, search, and startsWith methods. Note:You ...

  6. [LeetCode] 208. Implement Trie (Prefix Tree) ☆☆☆

    Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...

  7. 字典树(查找树) leetcode 208. Implement Trie (Prefix Tree) 、211. Add and Search Word - Data structure design

    字典树(查找树) 26个分支作用:检测字符串是否在这个字典里面插入.查找 字典树与哈希表的对比:时间复杂度:以字符来看:O(N).O(N) 以字符串来看:O(1).O(1)空间复杂度:字典树远远小于哈 ...

  8. 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  ...

  9. 【刷题-LeetCode】208. Implement Trie (Prefix Tree)

    Implement Trie (Prefix Tree) Implement a trie with insert, search, and startsWith methods. Example: ...

随机推荐

  1. 【JLOI2013】卡牌游戏

    题面 题解 概率$dp$ 设$f[i][j]$表示还剩$i$个人时,第$j$个人获胜的概率. 边界$f[1][1] = 1$ 转移: 枚举庄家抽到的卡牌$k$,得到这一轮被淘汰的位置$c$. 可以知道 ...

  2. Gitlab+Jenkins学习之路(六)之Jenkins部署、升级和备份

    一.什么是持续集成? (1)Continuous integration(CI) 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员至少集成一次,也就意味着每天可能会发生多次集 ...

  3. .net core中automapper的使用

    automapper 是将两个类中的相同字段进行映射,也可以指定字段进行映射:将 UserDao的id 映射为 User 的age CreateMap<UserDao, User>() . ...

  4. MYSQL创建表的约束条件(可选)

    一.常用的一些约束条件 一.创建表的完整语法1.创建表的万能模板:create table 库名.表名( 字段名1 类型[(宽度) 约束条件], 字段名2 类型[(宽度) 约束条件], 字段名3 类型 ...

  5. systemctl start nginx timeout

    昨儿个研究docker ,搭建私有仓库.想着用nginx代理一下仓库地址.方式使用80端口,于是愉快的下载,编辑,安装nginx.创建nginx.service作为系统启动服务. 结果......,多 ...

  6. ThinkPHP3.2开发仿京东商城项目实战视频教程

    ThinkPHP3.2仿京东商城视频教程实战课程,ThinkPHP3.2开发大型商城项目实战视频 第一天 1.项目说明 2.时间插件.XSS过滤.在线编辑器使用 3.商品的删除 4.商品的修改完成-一 ...

  7. hdfs命令大全

    hdfs常用命令: 第一部分:hdfs文件系统命令 第一类:文件路径增删改查系列: hdfs dfs -mkdir dir  创建文件夹 hdfs dfs -rmr dir  删除文件夹dir hdf ...

  8. socket 编程 : shutdown vs close

    TCP/IP 四次挥手 首先作者先描述一下TCP/IP 协议中四次挥手的过程,如果对此已经熟悉的读者可以跳过本节. 四次挥手 这是一个很经典的示例图,众所周知tcp socket 在一个生命周期中有很 ...

  9. Vue03

    5.组件化开发 组件[component] 在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个功能相关的[HTML ...

  10. g2蚂蚁数据可视化折线图,点位坐标label 图形文本设置

    应用g2可视化插件画了个粉丝分析图 要求显示如图所见的节点参数,查看文档蚂蚁图形文本设置,得知需要引入如下代码: chart.point().position('update*praises').la ...