题目描述:
给你一个字符串 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 <= 105
1 <= x, y <= 104
s 只包含小写英文字母。
方法1:
主要思路:解题汇总链接
(1)使用单调栈实现贪心;
(2)贪心的策略是每次尽量的先将权重大的子字符串删除,若删除完了,再从剩余的字符中删除一个权重较小的子字符串,
(3)然后判断是否能够删除可能存在的权重较大的子字符串,若能,则接着删除,若不能,则接着再去找一个权重较小的字符串;
(4)直到判断完所有的字符;
class Solution {
public:
//获得删除两个两个子字符串的数量
void get_count(string& s, char first_ch, char second_ch, int& count_ch_first, int& count_ch_second) {
stack<char> st;
//先将原字符串使用栈进行存储,存储过程中删除所有的权重较大的子字符串
for (char ch : s) {
if (!st.empty() && ch == second_ch && st.top() == first_ch) {//删除子字符串
st.pop();
++count_ch_first;//统计删除子字符串的数量
}
else {
st.push(ch);//压入字符
}
}
stack<char> st_tmp;//辅助栈, 存储字符
while (!st.empty()) {//判断完所有的字符
if (!st.empty() && !st_tmp.empty() && st.top() == second_ch && st_tmp.top() == first_ch) {//说明可以删除一个权重较小的子字符串
++count_ch_second;//统计权重较小的子字符串的数量
//删除子字符串
st.pop();
st_tmp.pop();
//判断是否可能进一步删除权重较大的字符串
while (!st.empty() &&!st_tmp.empty() && st.top() == first_ch && st_tmp.top() == second_ch) {
++count_ch_first;//统计删除权重较大的子字符串的数量
//删除子字符串
st.pop();
st_tmp.pop();
}
}
else {//压入到辅助栈中
st_tmp.push(st.top());
st.pop();
}
}
return;
}
int maximumGain(string s, int x, int y) {
int first = 0, second = 0;
int res = 0;
//根据权重的大小,决定先删除那个子字符串
if (x > y) {
get_count(s, 'a', 'b', first, second);
res = x * first + y * second;
}
else {
get_count(s, 'b', 'a', first, second);
res = y * first + x * second;
}
return res;
}
};