Implement a trie with insert, search, and startsWith methods.
Note:
You may assume that all inputs are consist of lowercase letters a-z.
参考百度百科:Trie树
a 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");