字典树是一种数据结构,也叫前缀树、Trie树。比较常用的应用有前缀匹配和词频统计。其特点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
浏览器的搜索算法就是字典树的一种典型应用:

字典树的特性
- 根节点不包含字符,除了根节点其他每个节点都只包含一个字符。根节点不包含字符的目的是为了能包括所有字符串。
- 从根节点到每一个节点,经过的字符串起来就是该节点对应的字符串。
- 每个节点的所有子节点包含的字符都不相同。

java实现字典树
定义根节点的结构体
root节点的结构体中包含一个长度为26的数组,代表’a’~‘z’。boolean类型变量isEnd表示是否为字符串末尾。
有的场景还会添加一个String类型的变量,用于存储从根节点到此节点串成的字符串。
class TrieNode {
TrieNode[] children = new TrieNode[26];
boolean isEnd = false;
}
Trie初始化
public class Trie {
TrieNode root;
public Trie() {
root = new TrieNode();
}
}
insert方法
insert方法用于向字典树中插入字符串word。
public void insert(String word) {
TrieNode tmp = root;
for (char c : word.toCharArray()) {
int index = c - 'a';
if (tmp.children[index] == null) {
tmp.children[index] = new TrieNode();
}
tmp = tmp.children[index];
}
tmp.isEnd = true;
}
search方法
search方法用于查询字典树中是否存在字符串word。除了要判断字典树中word开头的字符串是否存在,还需要判断isEnd。
public boolean search(String word) {
TrieNode tmp = root;
for (char c : word.toCharArray()) {
int index = c - 'a';
if (tmp.children[index] == null) {
return false;
}
tmp = tmp.children[index];
}
return tmp.isEnd;
}
startsWith方法
startsWith方法用于判断字典树中是否存在prefix开头的字符串,存在返回true,不存在则返回false。
public boolean startsWith(String prefix) {
TrieNode tmp = root;
for (char c : prefix.toCharArray()) {
int index = c - 'a';
if (tmp.children[index] == null) {
return false;
}
tmp = tmp.children[index];
}
return true;
}
LeetCode练习题
720. 词典中最长的单词
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)) {
continue;
}
if (longest.length() < word.length()) {
longest = word;
} else if (longest.length() == word.length() && longest.compareTo(word) > 0) {
longest = word;
}
}
return longest;
}
class Trie {
class TrieNode {
TrieNode[] children = new TrieNode[26];
boolean isEnd = false;
}
TrieNode root = new TrieNode();
public void insert(String word) {
TrieNode tmp = root;
for (char c : word.toCharArray()) {
int index = c - 'a';
if (tmp.children[index] == null) {
tmp.children[index] = new TrieNode();
}
tmp = tmp.children[index];
}
tmp.isEnd = true;
}
public boolean search(String word) {
TrieNode tmp = root;
for (char c : word.toCharArray()) {
int index = c - 'a';
if (tmp.children[index] == null) {
return false;
}
// 区别于208题的地方。
// 因为判断的word必须是由其他字符串在末尾加上一位组成,
// 因此树中必须存在1~len-1位的字符串,且这些字符串也都满足这个要求
if (!tmp.children[index].isEnd) {
return false;
}
tmp = tmp.children[index];
}
return tmp.isEnd;
}
}

被折叠的 条评论
为什么被折叠?



