前綴樹
阿新 • • 發佈:2019-05-03
for 存儲 icu etc 尋找 ins 單元 相同 輸入
前綴樹:前綴直白理解就是單詞的前綴。
前綴樹的每個結點都會初始化為有26個空指針(這是用數組來存儲子節點的一種方法),生成一顆前綴樹就是不斷插入單詞。
舉個栗子,對一棵空樹,插入單詞cat,根節點的子節點root->children[‘c‘ - ‘a‘]此時為空指針,就對其new出一個結點來,再對新結點插入字符‘a‘。
應用:尋找元素從頭開始的異同性
421. 數組中兩個數的最大異或值
212. 單詞搜索 II
先說單詞搜索這道題:給定一個二維網格 board 和一個字典中的單詞列表 words,找出所有同時在二維網格和字典中出現的單詞。
單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母在一個單詞中不允許被重復使用。
示例:
輸入: words =["oath","pea","eat","rain"]
and board = [ [‘o‘,‘a‘,‘a‘,‘n‘], [‘e‘,‘t‘,‘a‘,‘e‘], [‘i‘,‘h‘,‘k‘,‘r‘], [‘i‘,‘f‘,‘l‘,‘v‘] ] 輸出:["eat","oath"]
說明:
你可以假設所有輸入都由小寫字母 a-z
組成。
提示:
- 你需要優化回溯算法以通過更大數據量的測試。你能否早點停止回溯?
- 如果當前單詞不存在於所有單詞的前綴中,則可以立即停止回溯。什麽樣的數據結構可以有效地執行這樣的操作?散列表是否可行?為什麽? 前綴樹如何?如果你想學習如何實現一個基本的前綴樹,請先查看這個問題: 實現Trie(前綴樹)
這道題折騰我好久....
首先用最笨的DFS,先把二維網絡的字符都記錄下來,比如‘a‘在哪些地方出現了。然後對待搜索的每個單詞,先看首字符有沒有在網格裏出現,出現了就以其為起點在網格裏慢慢搜。由於不能重復使用元素,就建了個set,每搜一個字符先判斷在set裏出現沒。這方法,看起來就很蠢...但一般的測試還能應付,後面的就超時了...
然後看提示,要避免搜不存在的前綴,這裏的意思是,如果網格搜索的時候碰到不是待搜索單詞的前綴,就可以不用搜了。
其次,用樹的好處是,如果有的單詞前綴相同,利用前綴樹一次搜過去就基本遍歷完了,但如果針對單個單詞一次次去DFS就很煩了。
class TrieNode { public: TrieNode* children[26]; string s; TrieNode() { s = ""; for(int i = 0;i<26;++i) children[i] = NULL; } }; class Solution { public: TrieNode* root; void insert(string word){ TrieNode* tmp = root; for(int i = 0;i<word.length();++i){ int c = word[i] - ‘a‘; if(!tmp->children[c]){ tmp->children[c] = new TrieNode(); } tmp = tmp->children[c]; } tmp->s = word; } vector<string> findWords(vector<vector<char>>& board, vector<string>& words) { vector<string> res; int n = board.size();if(n == 0) return res; int m = board[0].size();if(m == 0) return res; root = new TrieNode(); for(auto p:words) insert(p); for(int i = 0;i<n;++i){ for(int j = 0;j<m;++j){ // if(root->children[board[i][j] - ‘a‘]){ // DFS(board,root->children[board[i][j] - ‘a‘],i,j,res); // } DFS2(board,root,i,j,res); } } return res; } void DFS(vector<vector<char>>& board,TrieNode* tmp,int i,int j,vector<string>& res){ if(tmp->s.length()){ res.push_back(tmp->s); tmp->s.clear(); } char c = board[i][j]; board[i][j] = ‘#‘; if(i>0 && board[i-1][j]!=‘#‘ && tmp->children[board[i-1][j] - ‘a‘]) DFS(board,tmp->children[board[i-1][j] - ‘a‘],i-1,j,res); if(j>0 && board[i][j-1]!=‘#‘ && tmp->children[board[i][j-1] - ‘a‘]) DFS(board,tmp->children[board[i][j-1] - ‘a‘],i,j-1,res); if(i+1<board.size() && board[i+1][j]!=‘#‘ && tmp->children[board[i+1][j] - ‘a‘]) DFS(board,tmp->children[board[i+1][j] - ‘a‘],i+1,j,res); if(j+1<board[0].size() && board[i][j+1]!=‘#‘ && tmp->children[board[i][j+1] - ‘a‘]) DFS(board,tmp->children[board[i][j+1] - ‘a‘],i,j+1,res); board[i][j] = c; } void DFS2(vector<vector<char>>& board,TrieNode* tmp,int i,int j,vector<string>& res){ char c = board[i][j]; if(c == ‘#‘ || !tmp->children[c - ‘a‘]) return; tmp = tmp->children[c - ‘a‘]; if(tmp->s.length()){ res.push_back(tmp->s); tmp->s.clear(); } board[i][j] = ‘#‘; if(i>0) DFS2(board,tmp,i-1,j,res); if(j>0) DFS2(board,tmp,i,j-1,res); if(i+1<board.size()) DFS2(board,tmp,i+1,j,res); if(j+1<board[0].size()) DFS2(board,tmp,i,j+1,res); board[i][j] = c; } };
前綴樹