每日算法:洛谷U535982 J-A 小梦的AB交换

题目描述

小梦有一个长度为 2∗n 的 AB 串 s,即 s 中只包含 "A" 和 "B" 两种字符,且其中恰好有 n 个 "A" 和 n 个 "B"。

他可以对 s 执行以下操作:

∙ 选择 i,j (1≤i,j≤2⋅n,i=j),并交换 si​ 和 sj​。

他想知道,需要至少多少次操作,才能使得 s 满足相邻的字符不相同,请你帮他算一算吧。

输入格式

本题有多组测试数据。

输入的第一行包含一个正整数 T,表示数据组数。

接下来包含 T 组数据,每组数据的格式如下:

第一行一个正整数 n,表示 s 长度的一半。

第二行一个长度为 2∗n 的字符串 s,保证只由 "A", "B" 两种字符构成。

输出格式

对于每组测试数据:

在单独的一行输出一个整数,表示最少进行的操作次数。

输入输出样例

输入 #1

2
3
AAABBB
3
ABAABB

输出 #1

1
1

说明/提示

【样例 1 解释】

交换 s2​=A 和 s5​=B,得到 s= "ABABAB",满足题意,一次交换即可。

【数据范围】

令 N 表示 T 组数据中 n 的总和。

对于 50% 的数据有:T=1,1≤N≤3。

对于所有的测试数据有: 1≤T≤100,1≤N≤106。

思考:这一题如果用正向思维去思考,那么会觉得很难,摸不着头脑,但是用逆向思维会发现非常简单!

观察:题目的要求是将原字符串不能有连续的A或B,那么最终答案一定是“ABAB.......”或“BABABA..........”的形式,因此我们可以先构造出这两个最终结果的字符串,然后跟原串进行比较,不相同的地方即为要操作的地方,又因为一次操作可以改变两个位置,我们将最后的结果除2,再对两个答案取最小值,就得到我们最终想要的结果啦

代码:

#include<bits/stdc++.h>

using namespace std;

int t,n;
string s;
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		cin>>s;
	string s1="",s2="";
//构建两种最终结果的字符串
	for(int i = 1;i <= n;i++){
		s1+="AB";
		s2+="BA";
	}
//分别记录得到两种最终结果需要的操作次数
	int ans1 = 0,ans2 = 0,ans = 0;
	
	for(int i = 0;i<2*n;i++){
//只要当前位置与预期不相等即认为需要操作
		if(s[i] != s1[i]) ans1++;
		if(s[i] != s2[i]) ans2++;
	}
//一次操作改变两个位置,因此要除以2 
	ans1/=2;
	ans2/=2;
//根据题目要求,取最小值
	ans = min(ans1,ans2);
//输出结果
	cout<<ans<<endl;
	}
	
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值