Leetcode0467. 环绕字符串中唯一的子字符串(medium)

目录

1. 问题描述

2. 思路与算法

3. 代码实现


1. 问题描述

把字符串 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.length <= 10^5
  • p 由小写英文字母构成

2. 思路与算法

        问题描述显得很生硬难懂,明显的翻译病。展开来理解的话如下所示:

        输入一个字符串 p,输出 满足以下条件的p 的子串的数量,:

  • 1,子串同时是 s 的子串
  • 2,不重复计数(比如说,p='abcab',ab出现了两次,不重复计)
  • 3,非空子串的定义是非空且连续的子序列

        例1,输入 p="a",p 的子串有 "a",满足条件的非空子串的数量是 1

        例2,输入 p="cac",p的非空子串有 "c", "a", "ca", "ac", "cac"
                满足条件的子串只有"c", "a"

        例3,输入 p="zab",p的子串有 "z", "a", "b", "za", "ab", "zab"
                全部满足条件。

        显而易见的是,如果p的一个子串满足条件,则该子串的子串也都满足条件。

        对p从左向右扫描局部最长严格(循环)升序子串,比如说,p='abdefgabcd',其中局部最长严格(循环)升序子串分别是'ab', 'defg', 'abcd'等。只要针对每个局部最长子串分别计算其包含的满足条件的子串即可。对于每个局部最长严格(循环)升序子串如果其长度为L,则它所包含的满足题设条件的子串数显然为2^L-1

        最长严格(循环)升序子串,是指一定是a后面跟b,b后面跟c,。。。,z后面跟a,的方式形成的子串。强调这个,是因为只有这种字符串才是s的子串。而s是循环的,所以z后面跟a是满足条件的。

        对p从左向右扫描局部最长严格(循环)升序子串,只需要一次性遍历,当发现下一个字符与上一个字符不满足以上“严格(循环)升序”的要求时,则当前最长严格(循环)升序子串结束了,重新开始下一个最长严格(循环)升序子串的搜索。显而易见的是,最长严格(循环)升序子串之间是不重叠的。

        但是以上处理没有排除子串的重复计数。比如说,如果p='abcdabc',"abc"会被统计到两次。进一步,比如说,p='abcdabceab',最后出现“ab”已经被前面的“abc”覆盖了,不应该再被统计了。        

        为了解决以上重复计数的问题,统计以每个字符作为结尾的最长连续子串的长度。例如:abcdbcd, 对于以d结尾的有abcd, bcd, cd和d, 而bcd、cd、d产生的子串都会被abcd所覆盖,这样就只需要针对“abcd”计数即可,它所包含的以“d”结尾的连续子串数量显然等于它的长度。而“abc”则另外作为以“c”结尾的连续子串,不作为“abcd”的子串来处理。

3. 代码实现

        

class Solution:
    def findSubstringInWraproundString(self, p: str) -> int:
        #if len(p)==1: return 1
        ans = 0
        d = dict.fromkeys(list(range(26)),0)
        curMaxSubStrLen = 1
        for k in range(len(p)):
            if k==0:
                curMaxSubStrLen = 1
            elif (p[k]=='a' and p[k-1]=='z') or (ord(p[k])-ord(p[k-1]))==1:
                curMaxSubStrLen += 1
            else:
                curMaxSubStrLen = 1
            d[ord(p[k])-97] = max(d[ord(p[k])-97],curMaxSubStrLen)
        #print(d)
        for key,val in d.items():
            ans += val

        return ans

        执行用时:100 ms, 在所有 Python3 提交中击败了36.49%的用户

        内存消耗:15.3 MB, 在所有 Python3 提交中击败了7.72%的用户

        

        回到总目录:Leetcode每日一题总目录(动态更新。。。)

猜你喜欢

转载自blog.csdn.net/chenxy_bwave/article/details/124958786
今日推荐