【第 74 场力扣双周赛】6021. 字符串中最多数目的子字符串(中等)

133 阅读3分钟

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”

一、题目描述

给你一个下标从 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 <= 105
  • pattern.length == 2
  • text 和 pattern 都只包含小写英文字母。

二、思路分析

读懂题目后不难发现,这道题是要考察贪心:求在 text 中插入 pattern 其中一个元素后, text 中包含了 patternpattern 的元素在 text 保持原本顺序的最大数量。

因为要保持顺序,那么很明显,pattern[0] 要在 pattern[1] 之前;又因为题意要求数量最大,因此可以得出贪心最优解:要么 pattern[0] 插在 text 最前面,要么 pattern[1] 插在 text 最后面。
这样一来问题就解决了大半,但还需要注意的是,pattern 的两个字符可能都是相同的,因此插在 text 中的哪个位置都无所谓。
还剩最后一个问题,这个所谓的最大数量应该怎么计算。题目告诉我们,可以删除 text 若干个字符(也可以不删除),也就是说 text 中每个 pattern[0] 可以与其后面的每个 pattern[1] 匹配成子序列,因此只要记录 pattern[0] 的数量为 cnt,当遇到 pattern[0] 的时候 cnt++ ,当遇到 pattern[1] 的时候最大数量加上 cnt 即可满足题意。

那么在动手敲代码之前,我们再整理一下思路:

  • pattern 两个字符都不相同的时候,分别将 pattern 的第一和第二个字符插在 text 的前面和后面,并定义 countcnt 分别标识 值等于插入字符的数量和题目要返回的最大数量。然后开始遍历新的 text ,如果当前元素等于插入的字符,count++,如果等于另一个字符,则 cnt += count 。直到遍历结束,return cnt 即可。
  • pattern 两个字符都相同的时候:取一个字符出来插在 text 后面,遍历时如果当前元素等于插入的字符,直接将最大数量加上遍历到的插入字符的数量,同时插入字符的数量也加 1 ,直到遍历结束即可。

三、AC 代码

function getCnt (text, a, b) {
    let count = 0;
    let cnt = 0;
    for (let i = 0; i < text.length; i ++) {
        if (text[i] === b) {
            cnt += count;
        } else if (text[i] === a) {
            count++;
        }
    }
    return cnt;
}

var maximumSubsequenceCount = function(text, pattern) {
    const [a, b] = pattern.split('');
    if (a === b) {
        let cnt = 0;
        let sum = 0;
        text += b;
        for (let i = 0; i < text.length; i ++) {
            if (text[i] === a) {
                sum += cnt;
                cnt++;
            }
        }
        return sum;
    }
    const text1 = `${a}${text}`;
    const text2 = `${text}${b}`;
    return Math.max(getCnt(text1, a, b), getCnt(text2, a, b));
};

四、总结