[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:

    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.

 

這道題給了我們一些單詞,讓我們通過輸入單詞的前綴和后綴來查找單詞的位置。單詞的位置就是其權重值,如果給定的前后綴能對應到不只一個單詞,那么返回最大的權重。首先,一個單詞如果長度為n的話,那么其就有n個前綴,比如對於單詞apple,其前綴即為"a", "ap", "app", "appl", "apple",同理,后綴也有n個。那么其組成的情況就有n2個,所以最簡單的方法就是把這n2個前后綴組成一個字符串,和當前權重建立映射。如果后面的單詞有相同的前后綴,直接用后面的大權重來覆蓋之前的權重即可。為了將前后綴encode成一個字符串,我們可以在中間加上一個非字母字符,比如'#',然后在查找的時候,我們先拼出“前綴#后綴”字符串,直接去哈希map中找即可,這種解法的WordFilter函數時間復雜度為O(NL^2),其中N是單詞個數,L是單詞長度。f函數時間復雜度為O(1),空間復雜度為O(NL^2),適合需要大量查找的情況下使用,參見代碼如下:

 

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比較叼啊。

 

類似題目:

Add and Search Word - Data structure design

 

參考資料:

https://discuss.leetcode.com/topic/113547/three-ways-to-solve-this-problem-in-java

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM