题意
给定一个由’A’和’B’组成的字符串,每次可以执行一下两种操作之一:
- 寻找一个字串"AB",删除;
- 寻找一个字串"BB",删除;
可以多次执行以上操作,问剩余字符串的最短长度。
思路
题目可以转化为维护一个栈,求最终栈的大小的最小值:
- ‘A’:入栈’A’;
- ‘B’:入栈’B’,或出栈栈顶;
贪心策略是能出栈就出栈。应为对于操作2.如果能出栈不出栈,等价于入栈一个’A’,由因为最后的结果肯定是"AAA ⋯ \cdots ⋯"或"BAAA ⋯ \cdots ⋯",显然答案不会更优。
代码
#include <bits/stdc++.h>
using namespace std;
#define fo(i, x, y) for (int i = (x); i <= (y); ++i)
#define fd(i, x, y) for (int i = (x); i >= (y); --i)
const int maxn = 2e5 + 5;
int n;
char str[maxn];
int getint()
{
char ch;
int res = 0, p;
while (!isdigit(ch = getchar()) && (ch ^ '-'));
p = ch == '-'? ch = getchar(), -1 : 1;
while (isdigit(ch))
res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
return res * p;
}
int main()
{
int T;
T = getint();
while (T--)
{
scanf("%s", str + 1);
n = strlen(str + 1);
int ans = n, sa = 0, sb = 0;
fo(i, 1, n)
{
if (str[i] == 'A') sa++;
else
{
sb++;
if (sa) sa--, sb--, ans -= 2;
else if (sb >= 2) sb -= 2, ans -= 2;
}
}
printf("%d\n", ans);
}
return 0;
}
总结
设一个合法的连续删除字串为 s s s则,则 ′ A ′ + s + ′ B ′ 、 ′ B ′ + s + ′ B ′ 、 s + " A B " 、 s + " B B " 'A'+s+'B'、'B'+s+'B'、s+"AB"、s+"BB" ′A′+s+′B′、′B′+s+′B′、s+"AB"、s+"BB"都是合法的,可以类比合法括号匹配/出入栈序列,用出入栈思想解决该问题。