从零学算法1717
1717.删除子字符串的最大得分
给你一个字符串 s 和两个整数 x 和 y 。你可以执行下面两种操作任意次。
删除子字符串 “ab” 并得到 x 分。
比方说,从 “cabxbae” 删除 ab ,得到 “cxbae” 。
删除子字符串"ba" 并得到 y 分。
比方说,从 “cabxbae” 删除 ba ,得到 “cabxe” 。
请返回对 s 字符串执行上面操作若干次能得到的最大得分。
示例 1:
输入:s = “cdbcbbaaabab”, x = 4, y = 5
输出:19
解释:
- 删除 “cdbcbbaaabab” 中加粗的 “ba” ,得到 s = “cdbcbbaaab” ,加 5 分。
- 删除 “cdbcbbaaab” 中加粗的 “ab” ,得到 s = “cdbcbbaa” ,加 4 分。
- 删除 “cdbcbbaa” 中加粗的 “ba” ,得到 s = “cdbcba” ,加 5 分。
- 删除 “cdbcba” 中加粗的 “ba” ,得到 s = “cdbc” ,加 5 分。
总得分为 5 + 4 + 5 + 5 = 19 。
示例 2:
输入:s = “aabbaaxybbaabb”, x = 5, y = 4
输出:20
提示:
1 <= s.length <= 10^5
1 <= x, y <= 10^4
s 只包含小写英文字母。
- 贪心:尽可能组合成更大得分的。
- 假设 x 总为更大得分,即应尽可能得到 ab 组合
- 若初始时 x < y,我们交换 xy 的值,同时把字符串 s 中的 ab 互换
- 首先我们要得到可执行操作的字符串,只要当前字符串为连续的仅由 a 和 b 组成的字符串(顺序不限),就也许能操作
- 操作时,利用栈的思想求 ab 的组合数,遇到 a 就入栈,遇到 b 时如果栈中有 a 就出栈,此时 ab 组合数 +1。经过该操作后剩余的字符顺序肯定都为 ba,所以只要知道此时两个字符的个数取最小值就是 ba 的组合数,因此在操作时顺便记录 a 和 b 的剩余个数
-
var maximumGain = function (s, x, y) {const getPoint = (str) => {let arr = str.split('')let a = 0 // a的个数let b = 0 // b的个数let abCount = 0let baCount = 0for (let i in arr) {if (arr[i] == 'a') a++else {// 此处用 a 的个数就能实现类似入栈出栈的效果if (a > 0) {a--abCount++} else b++}}baCount = Math.min(a, b)return abCount * x + baCount * y}if (x < y) {[x, y] = [y, x]s = s.replaceAll('a', '?').replaceAll('b', 'a').replaceAll('?', 'b')}const sArr = s.split('')const arr = []let i = 0let ans = 0while (i < sArr.length) {const char = sArr[i]let j = i + 1if (char == 'a' || char == 'b') {while (j < sArr.length && sArr[j] == 'a' || sArr[j] == 'b') j++if (j - i + 1 > 2) {ans += getPoint(s.slice(i, j))i = j + 1continue}}i++}return ans };