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

Implement a trie with insert, search, and startsWith methods.

Note:
You may assume that all inputs are consist of lowercase letters a-z.

参考百度百科:Trie树

trie, also called digital tree and sometimes radix tree or prefix tree (as they can be searched by prefixes)

The time complexity to insert and to search is O(m), where m is the length of the string.

标准Trie树的应用和优缺点

     (1) 全字匹配:确定待查字串是否与集合的一个单词完全匹配。如上代码fullMatch()。

     (2) 前缀匹配:查找集合中与以s为前缀的所有串。

     注意:Trie树的结构并不适合用来查找子串。这一点和前面提到的PAT Tree以及后面专门要提到的Suffix Tree的作用有很大不同。

      优点: 查找效率比与集合中的每一个字符串做匹配的效率要高很多。在o(m)时间内搜索一个长度为m的字符串s是否在字典里。Predictable O(k) lookup time where k is the size of the key

      缺点:标准Trie的空间利用率不高,可能存在大量结点中只有一个子结点,这样的结点绝对是一种浪费。正是这个原因,才迅速推动了下面所讲的压缩trie的开发。

什么时候用Trie?

It all depends on what problem you're trying to solve. If all you need to do is insertions and lookups, go with a hash table. If you need to solve more complex problems such as prefix-related queries, then a trie might be the better solution. 

 像word search II就是跟前缀有关,如果dfs发现当前形成的前缀都不在字典中,就没必要再搜索下去了,所以用trie不用hashSet

Easy version of implement Trie. TrieNode only contains TrieNode[] children, and boolean isWord two fields

 1 class Trie {
 2     class TrieNode {
 3         TrieNode[] children;
 4         boolean isWord;
 5         public TrieNode() {
 6             this.children = new TrieNode[26];
 7             this.isWord = false;
 8         }
 9     }
10     
11     TrieNode root;
12 
13     /** Initialize your data structure here. */
14     public Trie() {
15         this.root = new TrieNode(); 
16     }
17     
18     /** Inserts a word into the trie. */
19     public void insert(String word) {
20         if (word == null || word.length() == 0) return;
21         TrieNode cur = this.root;
22         for (int i = 0; i < word.length(); i ++) {
23             if (cur.children[word.charAt(i) - 'a'] == null) {
24                 cur.children[word.charAt(i) - 'a'] = new TrieNode();
25             } 
26             cur = cur.children[word.charAt(i) - 'a'];
27         }
28         cur.isWord = true;
29     }
30     
31     /** Returns if the word is in the trie. */
32     public boolean search(String word) {
33         TrieNode cur = this.root;
34         for (int i = 0; i < word.length(); i ++) {
35             if (cur.children[word.charAt(i) - 'a'] == null) return false;
36             cur = cur.children[word.charAt(i) - 'a'];
37         }
38         return cur.isWord;
39     }
40     
41     /** Returns if there is any word in the trie that starts with the given prefix. */
42     public boolean startsWith(String prefix) {
43         TrieNode cur = this.root;
44         for (int i = 0; i < prefix.length(); i ++) {
45             if (cur.children[prefix.charAt(i) - 'a'] == null) return false;
46             cur = cur.children[prefix.charAt(i) - 'a'];
47         }
48         return true;
49     }
50 }

Older version, TrieNode also has num and val fields, which might not be that useful.

 1 class TrieNode {
 2     // Initialize your data structure here.
 3     int num; //How many words go through this TrieNode
 4     TrieNode[] son; //collection of sons
 5     boolean isEnd;
 6     char val;
 7     
 8     public TrieNode() {
 9         this.num = 0;
10         this.son = new TrieNode[26];
11         this.isEnd = false;
12     }
13 }
14 
15 public class Trie {
16     private TrieNode root;
17 
18     public Trie() {
19         root = new TrieNode();
20     }
21 
22     // Inserts a word into the trie.
23     public void insert(String word) {
24         if (word==null || word.length()==0) return;
25         char[] arr = word.toCharArray();
26         TrieNode node = this.root;
27         for (int i=0; i<arr.length; i++) {
28             int pos = (int)(arr[i] - 'a');
29             if (node.son[pos] == null) {
30                 node.son[pos] = new TrieNode();
31                 node.son[pos].num++;
32                 node.son[pos].val = arr[i];
33             }
34             else {
35                 node.son[pos].num++;
36             }
37             node = node.son[pos];
38         }
39         node.isEnd = true;
40     }
41 
42     // Returns if the word is in the trie.
43     public boolean search(String word) {
44         char[] arr = word.toCharArray();
45         TrieNode node = this.root;
46         for (int i=0; i<arr.length; i++) {
47             int pos = (int)(arr[i] - 'a');
48             if (node.son[pos] == null) return false;
49             node = node.son[pos];
50         }
51         return node.isEnd;
52     }
53 
54     // Returns if there is any word in the trie
55     // that starts with the given prefix.
56     public boolean startsWith(String prefix) {
57         char[] arr = prefix.toCharArray();
58         TrieNode node = this.root;
59         for (int i=0; i<arr.length; i++) {
60             int pos = (int)(arr[i] - 'a');
61             if (node.son[pos] == null) return false;
62             node = node.son[pos];
63         }
64         return true;
65     }
66 }
67 
68 // Your Trie object will be instantiated and called as such:
69 // Trie trie = new Trie();
70 // trie.insert("somestring");
71 // trie.search("key");
原文地址:https://www.cnblogs.com/EdwardLiu/p/5050928.html