LeetCode 环绕字符串中唯一的子字符串(动态规划+hash表)

把字符串 s 看作是“abcdefghijklmnopqrstuvwxyz”的无限环绕字符串,所以 s 看起来是这样的:"…zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd…".
现在我们有了另一个字符串 p 。你需要的是找出 s 中有多少个唯一的 p 的非空子串,尤其是当你的输入是字符串 p ,你需要输出字符串 s 中 p 的不同的非空子串的数目。
注意: p 仅由小写的英文字母组成,p 的大小可能超过 10000。
示例 1:

输入: "a"
输出: 1
解释: 字符串 S 中只有一个"a"子字符。

示例 2:

输入: "cac"
输出: 2
解释: 字符串 S 中的字符串“cac”只有两个子串“a”、“c”。.

示例 3:

输入: "zab"
输出: 6
解释: 在字符串 S 中有六个子串“z”、“a”、“b”、“za”、“ab”、“zab”。.

思路分析: 由于子字符串是形如"abcd"或者“zab”这种连续的字符串,所以只要知道字符串的尾端字符和字符串的长度就可以唯一标记一个子字符串。使用map标记以ch结尾已经搜索到的最大长度
比如输入"zabcabcd"

index = 0,"z"是一个子字符串,dp[index] = 1,标记myMap['z'] = 1,res = 1
index = 1,"a"是一个子字符串,与前一个字符'z'是连续的,dp[index] = 1 + dp[index - 1],标记 myMap['a'] = dp[index],res += dp[index]
index = 2,"b"是一个子字符串,与前一个字符'a'是连续的,dp[index] = 1 + dp[index - 1],标记 myMap['b'] = dp[index],res += dp[index]
index = 3,"c"是一个子字符串,与前一个字符'b'是连续的,dp[index] = 1 + dp[index - 1],标记 myMap['c'] = dp[index],res += dp[index]
index = 4,"a"是一个子字符串,非连续,dp[index] = 1 ,由于之前搜到以'a'结尾的最长子字符串长度是2,所以这里不记入结果
index = 5,"b"是一个子字符串,与前一个字符'a'是连续的,dp[index] = 1 + dp[index -1] ,由于之前搜到以'b'结尾的最长子字符串长度是3,所以这里不记入结果
index = 6,"c"是一个子字符串,与前一个字符'b'是连续的,dp[index] = 1 + dp[index -1] ,由于之前搜到以'c'结尾的最长子字符串长度是4,所以这里不记入结果
index = 7,"d"是一个子字符串,与前一个字符'c'是连续的,dp[index] = 1 + dp[index -1] ,标记 myMap['d'] = dp[index],res += dp[index]
class Solution {
public:
    int findSubstringInWraproundString(string p) {
        int result = 0, pSize = p.size();
        if (pSize == 0){
            return result;
        }
        vector<int> dp(p.size(), 1);//dp[index]记录p串中以index为结尾的子字符串的长度
        map<char, int> myMap;//myMap[ch],标记已经找到的以字符ch结尾的最大长度
        //初始化第一个字符
        result = 1;
        myMap[p[0]] = 1;
        //扫描剩余的字符
        for (int index = 1; index < pSize; ++index){
            //只有碰到"za"或者“cd”这种连续的才需合并
            if (p[index] == p[index - 1] + 1 || (p[index] == 'a' && p[index - 1] == 'z')){
                dp[index] = dp[index - 1] + 1;//动态规划转移方程
            }
            //计算未搜索到的子字符串,myMap[p[index]]是已经搜索到的以p[index]结尾的最大长度
            if (dp[index] > myMap[p[index]]){
            //dp[index] - myMap[p[index]现在搜索到的长度 - 之前已经搜索到的最大长度
                result += (dp[index] - myMap[p[index]]);//添加新搜索到的长度
                myMap[p[index]] = dp[index];//更新以p[index]结尾的最大长度
            }
        }
        return result;
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/88915434