cf1685 B. Linguistics(div1)字符串+规律

传送门

题意

给定一个仅包含 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值