1. 程式人生 > >Leetcode 745. Prefix and Suffix Search

Leetcode 745. Prefix and Suffix Search

Problem:

Given many words, words[i] has weight i.

Design a class WordFilter that supports one function, WordFilter.f(String prefix, String suffix). It will return the word with given prefix and suffix with maximum weight. If no word exists, return -1.

Examples:

Input:
WordFilter(["apple"])
WordFilter.f("a", "e") // returns 0
WordFilter.f("b", "") // returns -1

Note:

  1. words has length in range [1, 15000].
  2. For each test case, up to words.length queries WordFilter.f may be made.
  3. words[i] has length in range [1, 10].
  4. prefix, suffix have lengths in range [0, 10].
  5. words[i] and prefix, suffix queries consist of lowercase letters only.

Solution:

  看到prefix和suffix,首先應該想到使用Trie這種資料結構的可能性,這道題涉及到字尾問題,所以我們需要設計一個函式rinsert來從單詞最後一個字元開始建立Trie(insert函式和rinsert函式的差別僅僅在於遍歷字串的順序相反而已)。因此tree是字首樹,rtree就成了字尾樹。在TrieNode中,我還維護了一個last陣列用於記錄走過這個節點的索引值。我們通過訪問一個TrieNode可以得到所有以該字首在words中的索引號,即startWith的函式功能。所以,我們只需要所有出現過prefix的陣列pre和所有出現過suffix的陣列suf中找到同時出現且最大的索引號即可。

Code:

 

 1 struct TrieNode{
 2     TrieNode *next[26];
 3     bool isEnd;
 4     vector<int> last;
 5     TrieNode():isEnd(false),last(0){
 6         for(int i = 0;i != 26;++i)
 7             next[i] = NULL;
 8     }
 9 };
10 class TrieTree{
11 public:
12     TrieTree(){
13         root = new
TrieNode(); 14 } 15 void insert(string word,int index) { 16 TrieNode *current = root; 17 current->last.push_back(index); 18 for(int i = 0;i != word.size();++i){ 19 if(current->next[word[i]-'a'] == NULL) 20 current->next[word[i]-'a'] = new TrieNode(); 21 current = current->next[word[i]-'a']; 22 current->last.push_back(index); 23 } 24 current->isEnd = true; 25 } 26 void rinsert(string word,int index) { 27 TrieNode *current = root; 28 current->last.push_back(index); 29 for(int i = word.size()-1;i >= 0;--i){ 30 if(current->next[word[i]-'a'] == NULL) 31 current->next[word[i]-'a'] = new TrieNode(); 32 current = current->next[word[i]-'a']; 33 current->last.push_back(index); 34 } 35 current->isEnd = true; 36 } 37 vector<int> startWith(string prefix){ 38 TrieNode *current = root; 39 for(int i = 0;i != prefix.size();++i){ 40 if(current->next[prefix[i]-'a'] == NULL) 41 return {}; 42 current = current->next[prefix[i]-'a']; 43 } 44 return current->last; 45 } 46 struct TrieNode *getRoot(){ 47 return root; 48 } 49 private: 50 TrieNode *root; 51 }; 52 class WordFilter { 53 public: 54 WordFilter(vector<string> words) { 55 for(int i = 0;i != words.size();++i){ 56 tree.insert(words[i],i); 57 rtree.rinsert(words[i],i); 58 } 59 60 } 61 62 int f(string prefix, string suffix) { 63 vector<int> pre = tree.startWith(prefix); 64 reverse(suffix.begin(),suffix.end()); 65 vector<int> suf = rtree.startWith(suffix); 66 for(int i = pre.size()-1;i >= 0;--i){ 67 for(int j = suf.size()-1;j >= 0;--j){ 68 if(pre[i] == suf[j]) 69 return pre[i]; 70 else if(pre[i] > suf[j]) 71 break; 72 } 73 } 74 return -1; 75 } 76 private: 77 TrieTree tree; 78 TrieTree rtree; 79 }; 80 81 /** 82 * Your WordFilter object will be instantiated and called as such: 83 * WordFilter obj = new WordFilter(words); 84 * int param_1 = obj.f(prefix,suffix); 85 */