Tire
一个字典树只要记住一个定义、两个核心操作就可以了。
son[p][u]:
- 其中
p代表当前节点在树中的索引 u代表下一个子节点(字符串中的下一位)的值son[p][u]代表 下一个下一个节点在树中的索引 (0代表没有创建索引)
我们还能发现,Trie和链表的数组实现具有异曲同工之妙。
链表中
ne[idx]代表下一个节点的索引;idx代表当前节点的索引Trie只是将它的子节点扩散成了多个
son[p][u]就相当于 ne[idx][u]
核心操作
开辟一个新节点
if (!son[p][u]) son[p][u] = ++idx;
向下遍历
p = son[p][u]
结合一下
for(int i = 0; str[i]; ++i){u = str[i] - 'a';if(!son[p][u])son[p][u] = ++idx;p = son[p][u];}
这样最终的p遍历出来代表一个特定字符串的结尾。
LeetCode
实现 Trie (前缀树)
需要特别注意的是,Tire的对象实现。
Tire对象实现就比较类似于链表的类实现了。
class Trie {P head;int idx = 0;class P{boolean is_end;P[] son = new P[26];}/** Initialize your data structure here. */public Trie() {head = new P();}/** Inserts a word into the trie. */public void insert(String word) {int u = 0;P p = this.head;for (int i = 0; i < word.length(); i ++){u = word.charAt(i) - 'a';if (p.son[u] == null) p.son[u] = new P();p = p.son[u];}p.is_end = true;}/** Returns if the word is in the trie. */public boolean search(String word) {int u = 0;P p = this.head;for (int i = 0; i < word.length(); i ++){u = word.charAt(i) - 'a';if (p.son[u] == null) return false;p = p.son[u];}return p.is_end;}/** Returns if there is any word in the trie that starts with the given prefix. */public boolean startsWith(String prefix) {int u = 0;P p = this.head;for (int i = 0; i < prefix.length(); i ++){u = prefix.charAt(i) - 'a';if (p.son[u] == null) return false;p = p.son[u];}return true;}}/*** Your Trie object will be instantiated and called as such:* Trie obj = new Trie();* obj.insert(word);* boolean param_2 = obj.search(word);* boolean param_3 = obj.startsWith(prefix);*/
或者
class Trie {int idx = 0;boolean is_end;Trie[] son = new Trie[26];/** Initialize your data structure here. */public Trie() {}/** Inserts a word into the trie. */public void insert(String word) {int u = 0;Trie p = this;for (int i = 0; i < word.length(); i ++){u = word.charAt(i) - 'a';if (p.son[u] == null) p.son[u] = new Trie();p = p.son[u];}p.is_end = true;}/** Returns if the word is in the trie. */public boolean search(String word) {int u = 0;Trie p = this;for (int i = 0; i < word.length(); i ++){u = word.charAt(i) - 'a';if (p.son[u] == null) return false;p = p.son[u];}return p.is_end;}/** Returns if there is any word in the trie that starts with the given prefix. */public boolean startsWith(String prefix) {int u = 0;Trie p = this;for (int i = 0; i < prefix.length(); i ++){u = prefix.charAt(i) - 'a';if (p.son[u] == null) return false;p = p.son[u];}return true;}}/*** Your Trie object will be instantiated and called as such:* Trie obj = new Trie();* obj.insert(word);* boolean param_2 = obj.search(word);* boolean param_3 = obj.startsWith(prefix);*/
