题目描述
给你一个字符串 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 只包含小写英文字母。
暴力思路:
优先选择得分高的字符串进行删除,每次删除后字符串发生变化,所以需要多次遍历字符串,错误信息:超时。。。
思路阻塞难点:
在字符串变化的情况下,如何减少字符串的遍历次数并确保删完所有可能产生的子串。
正确思路:
先通过交换分值和字符串逆序,确保先删字符串“ab”,借助栈结构处理,当前字符不为‘b’时入栈,直到为'b'了,检查栈顶是否是'a'。因为新的"ab"只能由被删除元素两侧合并产生。利用栈顶和字符串指针标记被删除元素两侧,就能确保删除字符串"ab"之后,产生的新"ab"被顺利找到。删除完"ab"产生的新字符串全被保留在栈里,由栈先进后出的规则可知,想删除原字符串的"ba",要删除的还是"ab"。。。这个栈当成普通数组遍历,用另一个栈辅助,重复上面的操作即可。
代码:
class Solution {
public int maximumGain(String s, int x, int y) {
int sum=0;
int i;
StringBuilder ss=new StringBuilder(s);
if(y>x)
{
i=x;
x=y;
y=i;
ss.reverse();
}
//确保先删ab
Stack <Character> t=new Stack<>();
Stack <Character> k=new Stack<>();
for(i=0;i<ss.length();i++)
{
if(ss.charAt(i)!='b')
{
t.push(ss.charAt(i));
}
else{
if(!t.empty()&&t.peek()=='a')
{
sum+=x;
t.pop();
}
else
{
t.push(ss.charAt(i));
}
}
}
while(!t.empty())
{
if(t.peek()!='b')
{
k.push(t.pop());
}
else{
if(!k.empty()&&k.peek()=='a')
{
k.pop();
t.pop();
sum+=y;
}
else
{
k.push(t.pop());
}
}
}
return sum;
}
}