[LeetCode] Prefix and Suffix Search 前後綴搜尋
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.
這道題給了我們一些單詞,讓我們通過輸入單詞的字首和字尾來查詢單詞的位置。單詞的位置就是其權重值,如果給定的前後綴能對應到不只一個單詞,那麼返回最大的權重。首先,一個單詞如果長度為n的話,那麼其就有n個字首,比如對於單詞apple,其字首即為"a", "ap", "app", "appl", "apple",同理,字尾也有n個。那麼其組成的情況就有n2
class WordFilter { public: WordFilter(vector<string> words) { for (int k = 0; k < words.size(); ++k) { for (int i = 0; i <= words[k].size(); ++i) { for (int j = 0; j <= words[k].size(); ++j) { m[words[k].substr(0, i) + "#" + words[k].substr(words[k].size() - j)] = k; } } } } int f(string prefix, string suffix) { return (m.count(prefix + "#" + suffix)) ? m[prefix + "#" + suffix] : -1; } private: unordered_map<string, int> m; };
如果我們希望節省一些空間的話,可以使用下面的方法。使用兩個雜湊map,一個建立所有字首和權重陣列之間的對映,另一個建立所有後綴和權重陣列之間的對映。在WordFilter函式中,我們遍歷每個單詞,然後先遍歷其所有字首,將遍歷到的字首的對映陣列中加入當前權重,同理再遍歷其所有後綴,將遍歷到的字尾的對映陣列中加入當前權重。在搜尋函式f中,首先判斷,如果字首或字尾不存在的話,直接返回-1。否則我們分別把字首和字尾的權重陣列取出來,然後用兩個指標i和j,分別指向陣列的最後一個位置。當i和j不小於0時進行迴圈,如果兩者的權重相等,直接返回,如果字首的權重陣列值大,則j自減1,反之i自減1,這種解法的WordFilter函式時間複雜度為O(NL),其中N是單詞個數,L是單詞長度。f函式時間複雜度為O(N),空間複雜度為O(NL),參見程式碼如下:
解法二:
class WordFilter { public: WordFilter(vector<string> words) { for (int k = 0; k < words.size(); ++k) { for (int i = 0; i <= words[k].size(); ++i) { mp[words[k].substr(0, i)].push_back(k); } for (int i = 0; i <= words[k].size(); ++i) { ms[words[k].substr(words[k].size() - i)].push_back(k); } } } int f(string prefix, string suffix) { if (!mp.count(prefix) || !ms.count(suffix)) return -1; vector<int> pre = mp[prefix], suf = ms[suffix]; int i = pre.size() - 1, j = suf.size() - 1; while (i >= 0 && j >= 0) { if (pre[i] < suf[j]) --j; else if (pre[i] > suf[j]) --i; else return pre[i]; } return -1; } private: unordered_map<string, vector<int>> mp, ms; };
moto72大神的帖子中還有第三種解法,但是C++中沒有startsWith()和endsWith()函式,以至於無法寫出C++版本的,還是Java比較叼啊。
類似題目:
參考資料: