[LeetCode] Unique Substrings in Wraparound String 封裝字符串中的獨特子字符串


 

Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz", so s will look like this: "...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....".

Now we have another string p. Your job is to find out how many unique non-empty substrings of p are present in s. In particular, your input is the string p and you need to output the number of different non-empty substrings of p in the string s.

Note: p consists of only lowercase English letters and the size of p might be over 10000.

Example 1:

Input: "a"
Output: 1

Explanation: Only the substring "a" of string "a" is in the string s.

 

Example 2:

Input: "cac"
Output: 2
Explanation: There are two substrings "a", "c" of string "cac" in the string s.

 

Example 3:

Input: "zab"
Output: 6
Explanation: There are six substrings "z", "a", "b", "za", "ab", "zab" of string "zab" in the string s.

 

這道題說有一個無限長的封裝字符串,然后又給了我們另一個字符串p,問我們p有多少非空子字符串在封裝字符串中。我們通過觀察題目中的例子可以發現,由於封裝字符串是26個字符按順序無限循環組成的,那么滿足題意的p的子字符串要么是單一的字符,要么是按字母順序的子字符串。這道題遍歷p的所有子字符串會TLE,因為如果p很大的話,子字符串很多,會有大量的滿足題意的重復子字符串,必須要用到trick,而所謂技巧就是一般來說你想不到的方法。我們看abcd這個字符串,以d結尾的子字符串有abcd, bcd, cd, d,那么我們可以發現bcd或者cd這些以d結尾的字符串的子字符串都包含在abcd中,那么我們知道以某個字符結束的最大字符串包含其他以該字符結束的字符串的所有子字符串,說起來很拗口,但是理解了我上面舉的例子就行。那么題目就可以轉換為分別求出以每個字符(a-z)為結束字符的最長連續字符串就行了,我們用一個數組cnt記錄下來,最后在求出數組cnt的所有數字之和就是我們要的結果啦,參見代碼如下:

 
解法一:
class Solution {
public:
    int findSubstringInWraproundString(string p) {
        vector<int> cnt(26, 0);
        int len = 0;
        for (int i = 0; i < p.size(); ++i) {
            if (i > 0 && (p[i] == p[i - 1] + 1 || p[i - 1] - p[i] == 25)) {
                ++len;
            } else {
                len = 1;
            }
            cnt[p[i] - 'a'] = max(cnt[p[i] - 'a'], len);
        }
        return accumulate(cnt.begin(), cnt.end(), 0);
    }
};

 

下面這種方法跟上面的基本一樣,就是在更新每個最大長度時,把差值累加到結果中,這跟最后統一加上最大值的效果一樣,參見代碼如下:

 

解法二:

class Solution {
public:
    int findSubstringInWraproundString(string p) {
        vector<int> cnt(26, 0);
        int res = 0, len = 0;
        for (int i = 0; i < p.size(); ++i) {
            int cur = p[i] - 'a';
            if (i > 0 && p[i - 1] != (cur + 26 - 1) % 26 + 'a') len = 0;
            if (++len > cnt[cur]) {
                res += len - cnt[cur];
                cnt[cur] = len;
            }
        }
        return res;
    }
};

 

參考資料:

https://discuss.leetcode.com/topic/70654/c-concise-solution

https://discuss.leetcode.com/topic/70658/concise-java-solution-using-dp/2

 

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


免責聲明!

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



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