Trie字首樹
阿新 • • 發佈:2021-09-17
轉載自:https://leetcode-cn.com/problems/implement-trie-prefix-tree/原題
Trie(發音類似 "try")或者說 字首樹 是一種樹形資料結構,用於高效地儲存和檢索字串資料集中的鍵。這一資料結構有相當多的應用情景,例如自動補完和拼寫檢查。
插入字串
我們從字典樹的根開始,插入字串。對於當前字元對應的子節點,有兩種情況:
- 子節點存在。沿著指標移動到子節點,繼續處理下一個字元。
- 子節點不存在。建立一個新的子節點,記錄在children 陣列的對應位置上,然後沿著指標移動到子節點,繼續搜尋下一個字元。
重複以上步驟,直到處理字串的最後一個字元,然後將當前節點標記為字串的結尾。
查詢字首
我們從字典樹的根開始,查詢字首。對於當前字元對應的子節點,有兩種情況:
- 子節點存在。沿著指標移動到子節點,繼續搜尋下一個字元。
- 子節點不存在。說明字典樹中不包含該字首,返回空指標。
重複以上步驟,直到返回空指標或搜尋完字首的最後一個字元。
若搜尋到了字首的末尾,就說明字典樹中存在該字首。此外,若字首末尾對應節點的isEnd為真,說明Trie中存在該string
程式碼
1 class Trie { 2 private: 3 vector<Trie*> children; 4 bool isEnd; 5 6 Trie* searchPrefix(stringprefix) { 7 Trie* node = this; 8 for (char ch : prefix) { 9 ch -= 'a'; 10 if (node->children[ch] == nullptr) { 11 return nullptr; 12 } 13 node = node->children[ch]; 14 } 15 return node; 16 }17 18 public: 19 Trie() : children(26), isEnd(false) {} 20 21 void insert(string word) { 22 Trie* node = this; 23 for (char ch : word) { 24 ch -= 'a'; 25 if (node->children[ch] == nullptr) { 26 node->children[ch] = new Trie(); 27 } 28 node = node->children[ch]; 29 } 30 node->isEnd = true; 31 } 32 33 bool search(string word) { 34 Trie* node = this->searchPrefix(word); 35 return node != nullptr && node->isEnd; 36 } 37 38 bool startsWith(string prefix) { 39 return this->searchPrefix(prefix) != nullptr; 40 } 41 };
字典樹的應用:
例題:https://leetcode-cn.com/problems/word-search-ii/
給定一個m x n 二維字元網格board和一個單詞(字串)列表 words,找出所有同時在二維網格和字典中出現的單詞。
單詞必須按照字母順序,通過 相鄰的單元格 內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母在一個單詞中不允許被重複使用。
輸入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
輸出:["eat","oath"]
實現:
1 from collections import defaultdict 2 3 4 class Trie: 5 def __init__(self): 6 self.children = defaultdict(Trie) 7 self.word = "" 8 9 def insert(self, word): 10 cur = self 11 for c in word: 12 cur = cur.children[c] 13 cur.is_word = True 14 cur.word = word 15 16 17 class Solution: 18 def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: 19 trie = Trie() 20 for word in words: 21 trie.insert(word) 22 23 def dfs(now, i1, j1): 24 if board[i1][j1] not in now.children: 25 return 26 27 ch = board[i1][j1] 28 29 now = now.children[ch] 30 if now.word != "": 31 ans.add(now.word) 32 33 board[i1][j1] = "#" 34 for i2, j2 in [(i1 + 1, j1), (i1 - 1, j1), (i1, j1 + 1), (i1, j1 - 1)]: 35 if 0 <= i2 < m and 0 <= j2 < n: 36 dfs(now, i2, j2) 37 board[i1][j1] = ch 38 39 ans = set() 40 m, n = len(board), len(board[0]) 41 42 for i in range(m): 43 for j in range(n): 44 dfs(trie, i, j) 45 46 return list(ans)