题意
给定一个仅包含 A A A 或 B B B 的字符串 s s s ,并给出 4 4 4 个数字分别代表字符串 A A A 、 B B B 、 A B AB AB、 B A BA BA 的个数,现需要用这四种字符串正好拼成字符串 s s s ,问是否可行。
由于取单独的 A A A、 B B B 能够组合成 A B AB AB 或 B A BA BA,因此考虑先使用 A B AB AB 和 B A BA BA,最后再使用单独的 A A A、 B B B 进行插空。
个人思路:当某一段子序列的两端与相邻字符相同(或为边界)时,将该子序列划分出来,并判断该子序列的长度。若长度 n n n 为偶数,且开头为 A A A,则可以正好由 n / 2 n/2 n/2 个 A B AB AB 组成,同理可得开头为 B B B 时可由 n / 2 n/2 n/2 个 B A BA BA 组成。当长度 n n n 为奇数时,可以通过 n / 2 n/2 n/2 个 A B AB AB 或 B A BA BA 组成。
因此判断可以使用 A B AB AB 或 B A BA BA 的个数是否大于等于拥有的 A B AB AB 和 B A BA BA 的个数,否则剩下的将无法插空。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
char s[N];
void solve(){
int a,b,ab,ba;
cin>>a>>b>>ab>>ba;
cin>>s+1;
int len=strlen(s+1);
int cnta=0,cntb=0;
for(int i=1;i<=len;i++){
if(s[i]=='A')
cnta++;
else
cntb++;
}
if(cnta!=a+ab+ba||cntb!=b+ab+ba){
cout<<"NO\n";
return ;
}
vector<int> x,y;
int sum=0;
for(int i=1,j;i<=len;i=j+1){
j=i;
while(j<len&&s[j]!=s[j+1])
j++;
if((j-i+1)%2==1)
sum+=(j-i+1)/2;
else{
int w=(j-i+1)/2;
if(s[i]=='A')
x.push_back(w);
else
y.push_back(w);
}
}
sort(x.begin(),x.end());
sort(y.begin(),y.end());
for(int i:x){
if(ab>=i)
ab-=i;
else
sum+=i-1;
}
for(int i:y){
if(ba>=i)
ba-=i;
else
sum+=i-1;
}
if(sum<ab+ba)
cout<<"NO\n";
else
cout<<"YES\n";
}
signed main(){
int t;
cin>>t;
while(t--)
solve();
return 0;
}