#646 (Div. 2)B. Subsequence Hate

题目描述

Shubham has a binary string s. A binary string is a string containing only characters “0” and “1”.
He can perform the following operation on the string any amount of times:
Select an index of the string, and flip the character at that index. This means, if the character was “0”, it becomes “1”, and vice versa.
A string is called good if it does not contain “010” or “101” as a subsequence — for instance, “1001” contains “101” as a subsequence, hence it is not a good string, while “1000” doesn’t contain neither “010” nor “101” as subsequences, so it is a good string.
What is the minimum number of operations he will have to perform, so that the string becomes good? It can be shown that with these operations we can make any string good.
A string a is a subsequence of a string b if a can be obtained from b by deletion of several (possibly, zero or all) characters.

Input

The first line of the input contains a single integer t (1≤t≤100) — the number of test cases.
Each of the next t lines contains a binary string s (1≤|s|≤1000).

Output

For every string, output the minimum number of operations required to make it good.

Example

input
7
001
100
101
010
0
1
001100
output
0
0
1
1
0
0
2

Note

In test cases 1, 2, 5, 6 no operations are required since they are already good strings.
For the 3rd test case: “001” can be achieved by flipping the first character — and is one of the possible ways to get a good string.
For the 4th test case: “000” can be achieved by flipping the second character — and is one of the possible ways to get a good string.
For the 7th test case: “000000” can be achieved by flipping the third and fourth characters — and is one of the possible ways to get a good string.

题目大意

给你一个只有0和1组成的字符串,你每次操作可以将某一位上的0翻转成1,1翻转成0。求至少反转多少次才能使得字符串中没有“101”或者“010”。

题目分析

为了让字符串中没有“010”或“101”,那么我们修改后的字符串只有:全是0,全是1,一边是0一边是1(如0001111)这三种结构。

对于一边是0一边是1这种结构,会有一个分割线,分割线的左边都修改为了一种数,而右边都修改成了另一种数。如000|1111,分割线左边全修改成了0,右边全修改成了1。
而对于全修改成0/1的情况,也可以看成是分割线在最左边或最右边的情况(如:|000000,|1111111)。

因此,我们可以枚举这个分割线的所有位置,并计算出分割线在该位置时需要的最小修改次数,最后找出最小的修改次数即可。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <map>
#include <unordered_map>
#include <queue>
#include <vector>
#include <set> 
#include <algorithm>
#include <iomanip>
#define LL long long
using namespace std;
const int N=1005;
int main()
{
    int t;
	cin>>t;
	while(t--)
	{
		string s;
		cin>>s;
		int cnt0=0,cnt1=0;        //表示分割线的右边的0/1数量
		//因为一开始分割线位于字符串的最左边(|00010010)
		for(int i=0;i<s.size();i++)   //所以一开始cnt存的是整个字符串中0/1的数量
		if(s[i]=='0') cnt0++;
		else cnt1++;
		
		int k0=0,k1=0;           //表示分割线左边0/1的数量(一开始都是0)
		int ans=min(cnt0,cnt1);  //记录答案(全局最小修改次数)
		for(int i=0;i<s.size();i++)  //枚举分割线的位置
		{
			if(s[i]=='0') k0++,cnt0--;   //分割线右移,cnt和k相应的增减
			else k1++,cnt1--;
			
			ans=min(ans,min(k0,k1)+min(cnt0,cnt1));  //跟新最小值
		}
		cout<<ans<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值