# 【LeetCode】 208. Implement Trie (Prefix Tree) ## Description > Implement a trie with `insert`, `search`, and `startsWith` methods. > Note: > * You may assume that all inputs are consist of lowercase letters `a-z`. > * All inputs are guaranteed to be non-empty strings. > 實作一個字典樹包含`insert`、`search`和`startsWith`等方法。 > 提示: > * 你可以假設所有的輸入都只會包含小寫英文字母`a-z`。 > * 所有輸入都保證不會是空字串。 ## Example: ``` Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // returns true trie.search("app"); // returns false trie.startsWith("app"); // returns true trie.insert("app"); trie.search("app"); // returns true ``` ## Solution * 這一題要實作資料結構中的字典樹,不知道是什麼的可以參照[wiki](https://zh.wikipedia.org/wiki/Trie)。 * 簡單來說它就是一棵樹,每個節點底下有`a~z`共`26`個子節點。 * 每次要新增單字進去的時候,就依序把每個字母對應的節點加進去,最後在單字結束的地方做個標記。 * 假設加入`abc`,就依序新增`a->b->c`三個節點(注意,他們是父子關係),並在`c`節點加上標記。 * 查詢的時候就去檢查單字的字母對應的節點是否存在,並且確認結束點有沒有標記。 * 如果沒有檢查標記,那上面加入`abc`的時候,因為`a->b`節點都存在,就會誤判`ab`也曾加入過。 * 而檢查前序字串就不需檢查標記,其餘都和查詢一樣。 --- * 解題歸解題,可以仔細想想這樣的結構有什麼好處? * 既然都叫做字典樹,那我們就拿字典來舉例。 * 試想今天你需要儲存一個字典量的單字,並且要有查詢功能。如果單純使用`string[]`或是`vector<string>`去儲存,那麼我們就需要大量的空間。 * 字典樹的好處在於可以有效壓縮需要的儲存空間,因為如果有單字前面相同,相同的部分都不需要額外的空間。 * 舉個例子:如果你已經建立了`apple`,因為`app`節點已經存在,所以只需要加上標記而不用其他動作。 ### Code ```C++=1 class Trie { public: bool isWord; Trie* node[26]; //Next letter's node. /** Initialize your data structure here. */ Trie() { isWord = false; for(int i = 0; i < 26; i++) this->node[i] = NULL; } /** Inserts a word into the trie. */ void insert(string word) { if(word.empty()) { this->isWord = true; return; } if(!this->node[word.front() - 'a']) { this->node[word.front() - 'a'] = new Trie; } this->node[word.front() - 'a']->insert(word.substr(1)); } /** Returns if the word is in the trie. */ bool search(string word) { if(word.empty()) return this->isWord; if(!this->node[word.front() - 'a']) return false; return this->node[word.front() - 'a']->search(word.substr(1)); } /** Returns if there is any word in the trie that starts with the given prefix. */ bool startsWith(string prefix) { if(prefix.empty()) return true; if(!this->node[prefix.front() - 'a']) return false; return this->node[prefix.front() - 'a']->startsWith(prefix.substr(1)); } }; /** * Your Trie object will be instantiated and called as such: * Trie* obj = new Trie(); * obj->insert(word); * bool param_2 = obj->search(word); * bool param_3 = obj->startsWith(prefix); */ ``` ###### tags: `LeetCode` `C++`