G. ABBC или BACB G. ABBC 或 BACB题解

G. ABBC или BACB G. ABBC 或 BACB题解

  • 链接:[https://codeforces.com/contest/1873/problem/G]

题目大意:

给定 是由字符 A和 B组成的 s 字符串。一开始,你没有硬币。你可以执行两种作:
  • 选择一个 †AB子字符串,替换为 BC,然后获得一枚硬币。
  • 选择一个 †BA子字符串,替换为 CB,然后获得一枚硬币。

问:最多能获得多少硬币

初步分析:

举例s字符串为ABBA,AB变为BC BA变为CB,发现没有?无论怎样变A必定消失,因此原问题可以转化为最多可以消多少个A

对于试例AAAAABBAAAA,将第一个AB变为BC此后前面的A也全会被消,后面的BA也是同理;

因此可以得出一个B可以把前面或者后面的连续A消掉

或者说 一个B可以把一串连续的A消掉(只不过消前面还是后面罢了)

思考解法:

依据初步分析最后一句话可以得出:

若B的个数>=连续A串个数 则可以将所有A全部消掉;

反之则不行,(说明必有一串A或多串A不能被消掉,那为什么不让他为最短的那几串呢)

所以 当B的个数<A串个数 则 少几个就剪几个A串个数的;

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
	int t;
	cin>>t;
	while(t--)
	{
		string s;
		cin>>s;
		int n=s.size();
		vector <int> vr; //要的就是空数组;vr表每一串A的个数
		int cnt=0,cnu=0,cns=0,o=0;
		//cnt为一串A串中有几个A;cnu为一共有几个B;cns为最多能消几个A(即答案);o为有几个A串;
		for(int i=0;i<n;i++)//遍历;
		{
			if(s[i]=='A' &&  i==n-1)//注释1  先看最后的注释(如果不懂的话)
			{
				cnt++;
				cns+=cnt;
				vr.push_back(cnt),o++;
			}else if(s[i]=='A') cnt++;//记录A个数
			else if(s[i]=='B' )
			{
				cnu++;//B个数
				if(cnt>0) vr.push_back(cnt),o++;//注释2
				cns+=cnt;//先加全部的A,后面如果有必要再减
				cnt=0;//遇到B时说明上一个A串结束
				
			}
		}
		sort(vr.begin(),vr.end());//小到大排序
		for(int i=0;i<o-cnu;i++)//A串个数比B个数多几个,就减几个
		{
			cns-=vr[i];
		 } 
		
		cout<<cns<<endl;
		
	}
	return 0;
 } 

注释:1.当遇到BAAAAA时最后不会触发if(s[i]==‘B’)不会记录最后一个A串,所以特判;

2.为什么特判cnt>0? 遇到ABBA,在第二个B时,多加了一个A串个数 同时cnt==0 vr数组也会多一个0 不对

反思:转化问题+菜就多练!!!

最后:如果对我有什么建议或是哪里错了

欢迎指出

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值