Leetcode2207. 字符串中最多数目的子字符串

Leetcode2207. 字符串中最多数目的子字符串,第1张

目录

1. 题目描述

2. Naive Approach-枚举遍历

3. 优化实现


1. 题目描述

给你一个下标从 0 开始的字符串 text 和另一个下标从 0 开始且长度为 2 的字符串 pattern ,两者都只包含小写英文字母。


你可以在 text 中任意位置插入 一个 字符,这个插入的字符必须是 pattern[0] 或者 pattern[1] 。


注意,这个字符可以插入在 text 开头或者结尾的位置。


请你返回插入一个字符后,text 中最多包含多少个等于 pattern 的 子序列 。


子序列 指的是将一个字符串删除若干个字符后(也可以不删除),剩余字符保持原本顺序得到的字符串。


示例 1:

输入:text = "abdcdbc", pattern = "ac"
输出:4
解释:
如果我们在 text[1] 和 text[2] 之间添加 pattern[0] = 'a' ,那么我们得到 "abadcdbc" 。


那么 "ac" 作为子序列出现 4 次。


其他得到 4 个 "ac" 子序列的方案还有 "aabdcdbc" 和 "abdacdbc" 。


但是,"abdcadbc" ,"abdccdbc" 和 "abdcdbcc" 这些字符串虽然是可行的插入方案,但是只出现了 3 次 "ac" 子序列,所以不是最优解。


可以证明插入一个字符后,无法得到超过 4 个 "ac" 子序列。


示例 2:

输入:text = "aabb", pattern = "ab"
输出:6
解释:
可以得到 6 个 "ab" 子序列的部分方案为 "aaabb" ,"aaabb" 和 "aabbb" 。


提示:

  • 1 <= text.length <= 10^5
  • pattern.length == 2
  • text 和 pattern 都只包含小写英文字母。


来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximize-number-of-subsequences-in-a-string
著作权归领扣网络所有。


商业转载请联系官方授权,非商业转载请注明出处。


2. Naive Approach-枚举遍历

        先做一个傻傻的算法至少有两个作用:(1)帮助理解问题的要点,尤其是(可能的)性能瓶颈要点;(2) 提供一个验证的benchmark,傻傻的办法比较容易保证功能正确,而“聪明”的解决方案则可能很难直接判断正确性和完备性。


        用pattern[0]和pattern[1]分别插入输入序列的text.length+1个可能的位置,总共2*(text.length+1)种情况,针对每种情况分别统计其中包含的子序列等于pattern的个数。


        解决了遍历问题,还有一个内层的问题需要解决,即(插入一个字符后的)字符串包含多少个pattern的统计方法。


由于要保证pattern[0]和pattern[1]的顺序,可以以字符串中出现的每个pattern[0]去找出现在它之后的pattern[1]的次数,这就是由某个pattern[0]能够构造出来的子序列个数,然后再累计每个pattern[0]的子序列个数即可。


         代码如下:

class Solution:
    def maximumSubsequenceCount(self, text: str, pattern: str) -> int:
        def countSubSeq(t):
            p0_cnt     = 0
            subseq_cnt = 0
            for k in range(len(t)):
                if t[k] == pattern[0]:
                    p0_cnt += 1
                if t[k] == pattern[1]:
                    subseq_cnt += p0_cnt
            return subseq_cnt
        subseq_max = 0
        for k in range(len(text)+1):
            t_tmp = text[:k] + pattern[0] + text[k:]
            subseq_cnt = countSubSeq(t_tmp)
            # print(t_tmp,subseq_cnt)
            subseq_max = subseq_cnt if subseq_max

        其中,countSubSeq()的实现还有一点点小小的trick,从头到尾遍历查找pattern[0]个数记为p0_cnt,同时查找pattern[1],每次找到一个pattern[1],就给总的计数值加一个当前p0_cnt即可。


3. 优化实现

        做完了以上方案,可以发现,如果要插入pattern[0]的话那就应该要在所有pattern[1]之前;同样,如果要插入pattern[1]的话,就要插入在所有pattern[1]之后。


那就很简单了,只需要考虑将pattern[0]插入在头上,以及,pattern[1]插入在尾部两种情况就可以了。


剩下的就是同样调用countSubSeq()进行统计,并比较两种情况子序列个数取其较大者即可。


class Solution:
    def maximumSubsequenceCount(self, text: str, pattern: str) -> int:
        def countSubSeq(t):
            p0_cnt     = 0
            subseq_cnt = 0
            for k in range(len(t)):
                if t[k] == pattern[0]:
                    p0_cnt += 1
                if t[k] == pattern[1]:
                    subseq_cnt += p0_cnt
            if pattern[0] == pattern[1]:
                subseq_cnt = p0_cnt * (p0_cnt - 1) // 2                    
            return subseq_cnt

        subseq_cnt0 = countSubSeq(pattern[0] + text)
        subseq_cnt1 = countSubSeq(text + pattern[1])

        return subseq_cnt0 if subseq_cnt0>=subseq_cnt1 else subseq_cnt1  

        细心的小伙伴看到这里可能已经注意到了countSubSeq()的实现跟上一节相比有了一点点修改。


原因在于上一节的写法漏了一种特殊情况没有考虑,以致于出现统计错误,这个bug被leetcode的testcase精准抓捕。


具体是哪种特殊情况呢?留给小伙伴们思考。


        测试代码如下:

if __name__ == '__main__':
    
    sln = Solution()
    
    text = "abdcdbc"
    pattern = "ac"
    print(sln.maximumSubsequenceCount(text, pattern))
    
    text = "aabb"
    pattern = "ab"
    print(sln.maximumSubsequenceCount(text, pattern))
    
    text = "mffiqmrvjmkfmbnaivajzecfdta"
    pattern = "hh"
    print(sln.maximumSubsequenceCount(text, pattern))
    
    text = "fwymvreuftzgrcrxczjacqovduqaiig"
    pattern = "yy"    
    print(sln.maximumSubsequenceCount(text, pattern))  

回到主目录:笨牛慢耕的Leetcode解题笔记(动态更新。






)https://chenxiaoyuan.blog.csdn.net/article/details/123040889

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/563591.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-02
下一篇 2022-04-02

发表评论

登录后才能评论

评论列表(0条)