###### tags: `Leetcode` `medium` `design` `hash` `python` `c++` `Top 100 Liked Questions` # 208. Implement Trie (Prefix Tree) ## [題目連結:] https://leetcode.com/problems/implement-trie-prefix-tree/ ## 題目: A **trie** (pronounced as "try") or **prefix tree** is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker. Implement the Trie class: * ```Trie()``` Initializes the trie object. * ```void insert(String word)``` Inserts the string word into the trie. * ```boolean search(String word)``` Returns ```true``` if the string ```word``` is in the trie (i.e., was inserted before), and ```false``` otherwise. * ```boolean startsWith(String prefix)``` Returns ```true``` if there is a previously inserted string ```word``` that has the prefix ```prefix```, and ```false``` otherwise. ![](https://i.imgur.com/1Z7JVFs.png) ## 解題想法: * 題目為實作字典樹(前綴樹) * 字典樹的每一個node皆是map: * key: 當前字母 * val: map,所有與當前字母有關聯的下個字母 * **若當前字母為某單詞的結尾,則在其val中新增一個key為"#"** * 示意說明如下: ``` * 根節點為dict,裡面存的每個char也都為dict 想法: insert: a , ant , cat , and (尾部加上#表示為完整單詞) 則當search 'an'時: 因為 key 'n'的map裡面只有{t,d}沒有'#', 因此沒有該an單字 -> return False 再insert 單詞'an'時: 由於前面有'an'了 因此只要在n後面加上'#'即可 下次再search 'an'時 後面有'#' 所以就return True了 則: root: { a c } / \ { n '#' } { a } / \ \ { t d } { t } / \ \ {'#'} {'#'} {'#'} ``` * 同類型題目:[211. Design Add and Search Words Data Structure](/llmwVvuqQdKNXizscN4tMQ) ## Python: ``` python= class Trie(object): def __init__(self): self.root={} #根節點為dict,裡面存的每個char也都為dict def insert(self, word): """ :type word: str :rtype: None """ curMap=self.root for char in word: #給該char建立下一層dict if char not in curMap: curMap[char]={} #移到下一層找下個char curMap=curMap[char] #當字串結束 最後加上'#' curMap['#']=True def search(self, word): """ :type word: str :rtype: bool """ curMap=self.root for char in word: if char not in curMap: return False #若出現 則繼續往下層找 curMap=curMap[char] return True if '#' in curMap else False def startsWith(self, prefix): """ :type prefix: str :rtype: bool """ #此功能為: 是否存在以prefix為開頭的字串 curMap=self.root for char in prefix: if char not in curMap: return False curMap=curMap[char] return True result = Trie() result.insert('a') result.insert('ant') result.insert('cat') result.insert('and') print(result.search('an')) #Fasle result.insert('an') print(result.search('an')) #True print(result.startsWith('ca')) #True ``` ## C++: * 額外寫個TrieNode * 總共就26個字母: 指針數組 ``` cpp= #include<bits/stdc++.h> using namespace std; class TrieNode{ public: TrieNode* childMap[26]; bool wordEnd; //Constructor TrieNode(): wordEnd(false) { for (auto& child: childMap) child=nullptr; } }; class Trie{ public: Trie(){ root=new TrieNode(); } void insert(string word){ TrieNode* curMap=root; for (char val: word){ int num=val-'a'; if (!curMap->childMap[num]) curMap->childMap[num]=new TrieNode(); curMap=curMap->childMap[num]; } curMap->wordEnd=true; } bool search(string word){ TrieNode* curMap=root; for (char val: word){ int num=val-'a'; if (!curMap->childMap[num]) return false; curMap=curMap->childMap[num]; } return curMap->wordEnd; } bool startsWith(string prefix){ TrieNode* curMap=root; for (char val: prefix){ int num=val-'a'; if (!curMap->childMap[num]) return false; curMap=curMap->childMap[num]; } return true; } private: TrieNode *root; }; int main(){ Trie* res=new Trie(); res->insert("a"); res->insert("ant"); res->insert("cat"); res->insert("and"); bool test1=res->search("an"); bool test2=res->startsWith("an"); cout<<test1<<" ,"<<test2<<endl; // 0(false),1(true) return 0; } ```