贪心
考虑用连续的 $\texttt{A}$ 和 $\texttt{B}$ 把字符串切割成数个极长连续交替段,已知有四种类型的连续段,假设连续段长度为 $m$,下面是一些性质。
- $\texttt{ABA} \cdots \texttt{ABA}$:拆分为一个 $\texttt{A}$ 和总共 $\left\lfloor \dfrac{m}{2} \right\rfloor$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。
- $\texttt{BAB} \cdots \texttt{BAB}$:拆分为一个 $\texttt{B}$ 和总共 $\left\lfloor \dfrac{m}{2} \right\rfloor$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。
- $\texttt{AB} \cdots \texttt{AB}$:可拆分得到 $\dfrac{m}{2}$ 个 $\texttt{AB}$ 或通过消耗一个 $\texttt{A}$ 和一个 $\texttt{B}$ 拆分为总共 $\dfrac{m}{2} - 1$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。
- $\texttt{BA} \cdots \texttt{BA}$:可拆分得到 $\dfrac{m}{2}$ 个 $\texttt{BA}$ 或通过消耗一个 $\texttt{A}$ 和一个 $\texttt{B}$ 拆分为总共 $\dfrac{m}{2} - 1$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。
显然应该将字符串尽可能多地分割为 $\texttt{AB}$ 或者 $\texttt{BA}$ 段。为了减少损失,优先考虑 $\texttt{AB} \cdots \texttt{AB}$ 和 $\texttt{BA} \cdots \texttt{BA}$,尽量用无损手段完成匹配。
更简单的理解:将 $\texttt{AB} \cdots \texttt{AB}$ 拆成仅含有 $\texttt{AB}$ 的段落比消耗一个 $\texttt{A}$ 和一个 $\texttt{B}$ 放的 $\texttt{AB}$ 更多,$\texttt{BA} \cdots \texttt{BA}$ 同理。要尽可能多地完成这样的拆分就应该优先拆分长度更短的段落。
分割字符串后,优先考虑长度较小的 $\texttt{AB}$ 或者 $\texttt{BA}$ 段,能部分匹配就将其部分匹配,其余部分容易处理。时间复杂度 $O(|S| \log |S|)$。
#include<bits/stdc++.h>
using namespace std;
int n,a,b,ab,ba,las;
string c,s;
void solution(){
cin>>s>>a>>b>>ab>>ba,c.clear(),n=s.size(),s='#'+s;
c.push_back(s[1]);
for(int i=2;i<=n-1;i++){
if(s[i]!=s[i-1]||s[i]!=s[i+1]) c.push_back(s[i]);
else s[i]=='A' ? --a:--b;
}
if(n!=1) c.push_back(s[n]);
vector<int> aba,bab,abab,baba;
las=1,s=c,n=s.size(),s='#'+s;
s.push_back(s[n]);
for(int i=2;i<=n+1;i++) if(s[i]==s[i-1]){
if(s[i-1]=='A'&&s[las]=='A') aba.push_back((i-1)-las+1);
if(s[i-1]=='B'&&s[las]=='B') bab.push_back((i-1)-las+1);
if(s[i-1]=='B'&&s[las]=='A') abab.push_back((i-1)-las+1);
if(s[i-1]=='A'&&s[las]=='B') baba.push_back((i-1)-las+1);
las=i;
}
sort(aba.begin(),aba.end()),sort(bab.begin(),bab.end());
sort(abab.begin(),abab.end()),sort(baba.begin(),baba.end());
auto pa=abab.begin(),pb=baba.begin();
while(pa!=abab.end()||pb!=baba.end()){
static bool goa;
if(pa!=abab.end()&&pb!=baba.end()) goa=(*pa<=*pb);
else goa=(pb==baba.end());
if(goa){
int x=min(ab,*pa/2);
ab-=x,*pa-=x*2;
if(*pa!=0){
--a,--b,*pa-=2;
x=min(ba,*pa/2);
ba-=x,*pa-=x*2;
}
if(*pa!=0) a-=*pa/2,b-=*pa/2;
*pa=0,++pa;
}
else{
int x=min(ba,*pb/2);
ba-=x,*pb-=x*2;
if(*pb!=0){
--a,--b,*pb-=2;
x=min(ab,*pb/2);
ab-=x,*pb-=x*2;
}
if(*pb!=0) a-=*pb/2,b-=*pb/2;
*pb=0,++pb;
}
}
for(int &i:aba){
--a,--i;
int x=min(ab,i/2);
ab-=x,i-=x*2;
x=min(ba,i/2);
ba-=x,i-=x*2;
a-=i/2,b-=i/2,i=0;
}
for(int &i:bab){
--b,--i;
int x=min(ab,i/2);
ab-=x,i-=x*2;
x=min(ba,i/2);
ba-=x,i-=x*2;
a-=i/2,b-=i/2,i=0;
}
if(a>=0&&b>=0) cout<<"Yes"<<'\n';
else cout<<"No"<<'\n';
}
int T;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--) solution();
return 0;
}