Python 官方文档:入门教程 => 点击学习
目录一.前缀树1.什么是前缀树2.前缀树的举例二.前缀树的实现1.前缀树的数据结构2.插入字符串3.查找字符串4.查找前缀三.词典中最长的单词1.题目描述2.问题分析3.代码实现一.
字典树(Trie树)是一种树形数据结构,常用于字符串的存储和查找。字典树的核心思想是利用字符串之间的公共前缀来节省存储空间和提高查询效率。它是一棵多叉树,每个节点代表一个字符串的前缀,从根节点到叶子节点的路径组成一个字符串。
字典树的根节点不包含字符,每个子节点代表一个字符,从根节点到任意一个节点所经过的路径上的字符连接起来即为该节点所代表的字符串。每个节点可以存储一个或多个字符串,通常使用一个标志来标记一个节点代表的字符串是否存在。当需要在一组字符串中查找某个字符串时,可以利用字典树来实现高效的查找操作。
例如对字符串数组{"Goog","google","bai","baidu","a"}建立前缀树,此时我们可以很清晰的看到前缀树的一些特征:
力扣上的208题就是实现前缀树:力扣
在写代码的时候,我偏向于用哈希表来存储结点的信息,有的也可以用数组来存储结点的信息,本质上都是一样的
public class Trie {
Map<Character, Trie> next;
boolean isEnd;
public Trie() {
this.next = new HashMap<>();
this.isEnd = false;
}
public void insert(String Word) {
}
public boolean search(String word) {
return false;
}
public boolean startsWith(String prefix) {
return false;
}
}
public void insert(String word) {
Trie trie = this;//获得根结点
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null) {//当前结点不存在
trie.next.put(c, new Trie());//创建当前结点
}
trie = trie.next.get(c);//得到字符c的结点,继续向下遍历
}
trie.isEnd = true;
}
public boolean search(String word) {
Trie trie = this;//获得根结点
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null) {//当前结点不存在
return false;
}
trie = trie.next.get(c);//得到字符c的结点,继续向下遍历
}
return trie.isEnd;
}
public boolean startsWith(String prefix) {
Trie trie = this;//获得根结点
for (char c : prefix.toCharArray()) {
if (trie.next.get(c) == null) {//当前结点不存在
return false;
}
trie = trie.next.get(c);//得到字符c的结点,继续向下遍历
}
return true;
}
接下来是力扣上关于前缀树的一些题目
给出一个字符串数组words
组成的一本英语词典。返回words
中最长的一个单词,该单词是由words
词典中其他单词逐步添加一个字母组成。
若其中有多个可行的答案,则返回答案中字典序最小的单词。若无答案,则返回空字符串。
力扣:力扣
这是一道典型的前缀树的问题,但是这一题有一些特殊的要求,返回的答案是:
1.最长的单词
2.这个单词由其他单词逐步构成
3.长度相同返回字典序小的
因此我们需要对前缀树的相关代码进行修改,把字符串一一插入的代码还是不改变的,主要修改的是查找的代码,应该在 trie.next.get(c) == null在增加一个判断为false的条件,就是每一个结点都应该有一个标志true,表示每个节点都存在一个单词,最终一步步构成最长的单词(叶子结点的单词)
class Solution {
public String longestWord(String[] words) {
Trie trie = new Trie();
for (String word : words) {
trie.insert(word);
}
String longest = "";
for (String word : words) {
if (trie.search(word)) {
if (word.length() > longest.length() || ((word.length() == longest.length()) && (word.compareTo(longest) < 0))) {
longest = word;
}
}
}
return longest;
}
}
class Trie {
Map<Character, Trie> next;
boolean isEnd;
public Trie() {
this.next = new HashMap<>();
this.isEnd = false;
}
public void insert(String word) {
Trie trie = this;//获得根结点
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null) {//当前结点不存在
trie.next.put(c, new Trie());//创建当前结点
}
trie = trie.next.get(c);//得到字符c的结点,继续向下遍历
}
trie.isEnd = true;
}
public boolean search(String word) {
Trie trie = this;//获得根结点
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null || !trie.next.get(c).isEnd) {//当前结点不存在
return false;
}
trie = trie.next.get(c);//得到字符c的结点,继续向下遍历
}
return trie.isEnd;
}
}
到此这篇关于Java实现前缀树详解的文章就介绍到这了,更多相关Java前缀树内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Java实现前缀树详解
本文链接: https://lsjlt.com/news/211823.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0