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:
words
has length in range[1, 15000]
.- For each test case, up to
words.length
queriesWordFilter.f
may be made. words[i]
has length in range[1, 10]
.prefix, suffix
have lengths in range[0, 10]
.words[i]
andprefix, 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 */