LeetCode 0467.环绕字符串中唯一的子字符串

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 0467.环绕字符串中唯一的子字符串相关的知识,希望对你有一定的参考价值。

【LetMeFly】467.环绕字符串中唯一的子字符串

力扣题目链接:https://leetcode.cn/problems/unique-substrings-in-wraparound-string/

把字符串s看作是“abcdefghijklmnopqrstuvwxyz”的无限环绕字符串,所以s看起来是这样的:

  • "...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....".

现在给定另一个字符串p。返回s唯一p非空子串 的数量 。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 ≤ p . l e n g t h ≤ 1 0 5 1\\leq p.length\\leq 10^5 1p.length105
  • p p p 由小写英文字母构成

题目大意

给你一个全是小写字母的字符串p,让你找到其中所有的“连续递增子串”。

其中,“连续递增子串”满足:

后一个字母是前一个字母的下一个字母,字母z除外。

也就是说,a的下一个字母是b,b的下一个字母是c,…,z的下一个字母是a。

例如 “abc”、“xyz”、“zab”都是“连续递增子串”

思路

先讲一下我之前的思路,想直接看结论的话请点击这里

子串来自于连续“递增”串。也就是说某个串如果从左到右字母按字母序依次递增,这个串的所有连续子串都是答案。

于是我们只需要把原串划分成多个“连续递增串”,每个串的长度至少为1。这个步骤时间复杂度O(q.length)

对于某个划分出来的串(假设长度为l),它的连续子串的个数是“l + (l - 1) + (l - 2) + … + 1 = l * (l + 1) / 2”

但是这样会导致结果偏大,因为题目要求“唯一的p的非空子串”。其实我觉得改成“不同的”更好

如果仅计数,对于长度为l的串所需的时间复杂度就是O(1),但如果要去重(以时间复杂度为O(1)的哈希表为例),那时间复杂度就会上升为O(l2),显然会超时。

那么怎么办呢?接下来请出正题:动态规划。

方法一:动态规划

其实不难发现:如果答案串的长度定了,最后一个字符也定了,那么我们就可以唯一推断出这个字符串。

例如例三中“zab”的一个“连续递增子串”是“ab”。我们知道了“ab”的长度(2),也知道了“ab”的最后一个字母(b),因此我们就能还原出原串为“ab”。

同时:如果“ab”是答案串,那么“b”一定是答案串

这是因为“b”是“ab”的子串。

因此:

我们只需要记录以各个字母结尾的串的最大长度,并将它们加起来就是答案。

比如:用endBy[i] 代表以第i个小写字母结尾的串的最大长度,假设endBy[25] = 5,那么就说明存在以z结尾的串最大长度为5。也就是说p中存在子串“vwxyz”。这样我们就能得到以“z”结尾的符合条件的5个答案“vwxyz”、“wxyz”、“xyz”、“yz”、“z”。同时endBy[24]一定也不会为0,以“y”结尾的答案串累计道了endBy[24]中。

  • 时间复杂度 O ( n ) O(n) O(n),其中 n n n是字符串 p p p的长度。
  • 空间复杂度 O ( ∣ Σ ∣ ) O(|Σ|) O(Σ),其中 ∣ Σ ∣ |Σ| Σ是字符集的大小。本题字符串由小写字母构成,因此 ∣ Σ ∣ = 26 |Σ|=26 Σ=26

AC代码

C++

class Solution 
public:
    int findSubstringInWraproundString(string& p) 
        int endBy[26] = 0;
        int length = 0;
        for (int i = 0; i < p.size(); i++) 
            if (i && (p[i] - 'a') == (p[i - 1] - 'a' + 1) % 26) 
                length++;
            
            else 
                length = 1;
            
            endBy[p[i] - 'a'] = max(endBy[p[i] - 'a'], length);
        
        int ans = 0;
        for (int i = 0; i < 26; i++)
            ans += endBy[i];
        return ans;
    
;

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/124972046

以上是关于LeetCode 0467.环绕字符串中唯一的子字符串的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 467. 环绕字符串中唯一的子字符串 java

LeetCode 467 环绕字符串中唯一的子字符串[动态规划] HERODING的LeetCode之路

LeetCode 965. 单值二叉树 / 467. 环绕字符串中唯一的子字符串 / 699. 掉落的方块(线段树后面再写)

Leetcode 467.环绕字符串中的唯一子字符串

Leetcode 76.最小覆盖子串

vue中使用css modules替代scoped