Trie 树的模板

Trie 树的简介

Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树。他的核心思想是空间换时间,空间消耗大但是插入和查询有着很优秀的时间复杂度。

Trie 树的定义

Trie树的键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀(prefix),从根节点到当前结点的路径上的所有字母组成当前位置的字符串,结点可以保存当前字符串、出现次数、指针数组(指向子树)以及是否是结尾标志等等。

简图

实际上每个节点有一个end属性和一个字典长度的节点数组

Trie 树的实现

LeetCode 208. 实现 Trie (前缀树)

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

请你实现 Trie 类:

Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word 。
boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。
  示例: 输入
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
输出
[null, null, true, false, true, null, true] 解释
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // 返回 True
trie.search("app"); // 返回 False
trie.startsWith("app"); // 返回 True
trie.insert("app");
trie.search("app"); // 返回 True
  提示: 1 <= word.length, prefix.length <= 2000
word 和 prefix 仅由小写英文字母组成
insert、search 和 startsWith 调用次数 总计 不超过 3 * 104 次
class Trie {
class TrieNode {
boolean end;
TrieNode[] tns = new TrieNode[26];
}
TrieNode root;
public Trie() {
root = new TrieNode();
} public void insert(String word) {
TrieNode p = root;
for(int i = 0; i < word.length(); i++) {
int u = word.charAt(i) - 'a';
if(p.tns[u] == null) p.tns[u] = new TrieNode();
p = p.tns[u];
}
p.end = true;
} public boolean search(String word) {
TrieNode p = root;
for(int i = 0; i < word.length(); i++) {
int u = word.charAt(i) - 'a';
if(p.tns[u] == null) return false;
p = p.tns[u];
}
return p.end;
} public boolean startsWith(String prefix) {
TrieNode p = root;
for(int i = 0; i < prefix.length(); i++) {
int u = prefix.charAt(i) - 'a';
if(p.tns[u] == null) return false;
p = p.tns[u];
}
return true;
}
}

Trie 树的例题

LeetCode 211. 添加与搜索单词

LeetCode 211. 添加与搜索单词

请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。

实现词典类 WordDictionary :

WordDictionary() 初始化词典对象
void addWord(word) 将 word 添加到数据结构中,之后可以对它进行匹配
bool search(word) 如果数据结构中存在字符串与 word 匹配,则返回 true ;否则,返回  false 。word 中可能包含一些 '.' ,每个 . 都可以表示任何一个字母。
  示例: 输入:
["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
输出:
[null,null,null,null,false,true,true,true] 解释:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord("bad");
wordDictionary.addWord("dad");
wordDictionary.addWord("mad");
wordDictionary.search("pad"); // return False
wordDictionary.search("bad"); // return True
wordDictionary.search(".ad"); // return True
wordDictionary.search("b.."); // return True
  提示: 1 <= word.length <= 500
addWord 中的 word 由小写英文字母组成
search 中的 word 由 '.' 或小写英文字母组成
最多调用 50000 次 addWord 和 search
class WordDictionary {
class Node {
boolean end;
Node[] tns = new Node[26];
}
Node root;
public void insert(String s) {
Node p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if(p.tns[u] == null) p.tns[u] = new Node();
p = p.tns[u];
}
p.end = true;
}
public WordDictionary() {
root = new Node();
} public void addWord(String word) {
insert(word);
} public boolean search(String s) {
return dfs(s, root, 0);
}
public boolean dfs(String s, Node p, int idx) {
int n = s.length();
if(idx == n) return p.end;
char c = s.charAt(idx);
if(c == '.') {
for(int i = 0; i < 26; i++) {
if(p.tns[i] != null && dfs(s, p.tns[i], idx + 1)) return true;
}
return false;
}
else {
int u = c - 'a';
if(p.tns[u] == null) return false;
return dfs(s, p.tns[u], idx + 1);
}
}
}

LeetCode 720. 词典中最长的单词

给出一个字符串数组 words 组成的一本英语词典。返回 words 中最长的一个单词,该单词是由 words 词典中其他单词逐步添加一个字母组成。

若其中有多个可行的答案,则返回答案中字典序最小的单词。若无答案,则返回空字符串。

 

示例 1:

输入:words = ["w","wo","wor","worl", "world"]
输出:"world"
解释: 单词"world"可由"w", "wo", "wor", 和 "worl"逐步添加一个字母组成。
示例 2: 输入:words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
输出:"apple"
解释:"apply" 和 "apple" 都能由词典中的单词组成。但是 "apple" 的字典序小于 "apply"
  提示: 1 <= words.length <= 1000
1 <= words[i].length <= 30
所有输入的字符串 words[i] 都只包含小写字母。
class Solution {
class Trie {
class TrieNode {
boolean end;
TrieNode[] tns = new TrieNode[26];
}
TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String s) {
TrieNode p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if(p.tns[u] == null) {
p.tns[u] = new TrieNode();
}
p = p.tns[u];
}
p.end = true;
}
public boolean search(String s) {
TrieNode p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if(p.tns[u] == null) return false;
p = p.tns[u];
}
return p.end;
}
public boolean startsWith(String s) {
TrieNode p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if(p.tns[u] == null) return false;
p = p.tns[u];
}
return true;
}
public boolean query(String s) {
TrieNode p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if(p.tns[u] == null) return false;
if(p.tns[u].end == false) return false;
p = p.tns[u];
}
return true;
}
}
public String longestWord(String[] words) {
Trie t = new Trie();
for(String word : words) {
t.insert(word);
}
String ans = "";
for(String word : words) {
int lena = ans.length();
int lenb = word.length();
if(lenb < lena) continue;
if(lenb == lena && word.compareTo(ans) > 0) continue;
if(t.query(word)) ans = word;
}
return ans;
}
}

【数据结构与算法】Trie(前缀树)模板和例题的更多相关文章

  1. 第15个算法-实现 Trie (前缀树)(LeetCode)

    解法代码来源 :https://blog.csdn.net/whdAlive/article/details/81084793 算法来源:力扣(LeetCode)链接:https://leetcode ...

  2. 数据结构—— Trie (前缀树)

    实现一个 Trie (前缀树),包含 插入, 查询, 和 查询前缀这三个操作. Trie trie = new Trie(); trie.insert("apple"); trie ...

  3. python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie)

    python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie) 主要包括两部分内容:(1)利用python中的dict实现Trie:(2) ...

  4. leetcode 208. 实现 Trie (前缀树)

    实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = new Trie(); trie.insert(" ...

  5. 力扣208——实现 Trie (前缀树)

    这道题主要是构造前缀树节点的数据结构,帮助解答问题. 原题 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = ...

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

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

  7. 实现 Trie (前缀树)

    实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = new Trie(); trie.insert(" ...

  8. Java实现 LeetCode 208 实现 Trie (前缀树)

    208. 实现 Trie (前缀树) 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = new Trie() ...

  9. 力扣 - 208. 实现Trie(前缀树)

    目录 题目 思路 代码 复杂度分析 题目 208. 实现 Trie (前缀树) 思路 在我们生活中很多地方都用到了前缀树:自动补全,模糊匹配,九宫格打字预测等等... 虽然说用哈希表也可以实现:是否出 ...

  10. [leetcode] 208. 实现 Trie (前缀树)(Java)

    208. 实现 Trie (前缀树) 实现Trie树,网上教程一大堆,没啥可说的 public class Trie { private class Node { private int dumpli ...

随机推荐

  1. web常用开发工具

    1.WebStorm[推荐] WebStorm 是jetbrains公司旗下一款JavaScript 开发工具.目前已经被广大中国JS开发者誉为"Web前端开发神器"." ...

  2. 前端也能做AI

    殷圣魁 58架构师 7月16日 原文链接 前言 相信不少人看过一篇人工智能已经能实现自动编写HTML,CSS的文章,人工智能开始取代前端的一部分工作.前端开发行业真的被人工智能取代吗? 1.人工智能发 ...

  3. 使用java实现圆形运动

    1 package com.neuedu.test; 2 3 import java.awt.Graphics; 4 import java.awt.Image; 5 6 import com.neu ...

  4. 浅谈php web安全

    首先,笔记不是web安全的专家,所以这不是web安全方面专家级文章,而是学习笔记.细心总结文章,里面有些是我们phper不易发现或者说不重视的东西.所以笔者写下来方便以后查阅.在大公司肯定有专门的we ...

  5. linux实用技巧:在虚拟机vmware16软件上安装CentOs8.2虚拟机,重置可用源和安装输入法

    前言   开发服务器应用,需要使用到CentOs8.2,安装到虚拟机上方便快捷.   提前准备 Vmware 16虚拟机软件  下载VM16版本及以上的vmware虚拟机版本,否则没有CentOs8选 ...

  6. 论文解读(IDEC)《Improved Deep Embedded Clustering with Local Structure Preservation》

    Paper Information Title:<Improved Deep Embedded Clustering with Local Structure Preservation>A ...

  7. spring mvc通过客户端传值,controller获取Sort对象

    之前客户端需要根据需求按不同的排序方式查看数据,按照一种约定排序,比如1代表时间升序,2代表时间降序,3,4这种形式,然后后台根据这些值创建Sort对象. 后来发现完全多此一举,可以根据特定的方式,直 ...

  8. 5.1 Paralles 为虚拟机设置静态ip

    一.配置独立ip的环境 前面研究了k8s的组件,核心概念,网络模型,都了解了一遍,现在就要进入实战了,摆在面前的一座大山,必须克服才行---虚拟机搭建,及网络环境配置. 先说说本文的运行环境: mac ...

  9. 【故障公告】k8s 开船记:增加控制舱(control-plane)造成的翻船

    春节期间我们更换了 kubernetes 生产集群,旧集群的 kubernetes 版本是 1.17.0,新集群版本是 1.23.3,新集群上部署了 dapr,最近准备将更多独立部署的服务器部署到 k ...

  10. 显式锁之ReentrantLock实现

    下图是Lock接口清单,定义了一些抽象的锁操作.Java本身提供了内部锁机制,那么还需要显示Lock,何用?与内部加锁机制不同,Lock提供了无条件.可轮询.定时.可中断的锁获取操作:所有加锁和解锁的 ...