平衡字符串——尺取法

题目描述

一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。
如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?
如果 s 已经平衡则输出0。

Input

一行字符表示给定的字符串s

Output

一个整数表示答案

Examples

Input

QWER

Output

0

Input

QQWE

Output

1

Input

QQQW

Output

2

Input

QQQQ

Output

3

Notes

1<=n<=10^5

n是4的倍数

字符串中仅包含字符 'Q', 'W', 'E' 和 'R'.

解题思路

由于本题所求为一连续区间的长度,并且需要一个双指针来维护这个数组的移动,因此符合尺取法的条件。当区间符合要求时左指针右移,否则右指针右移。而是否符合要求的判断条件是,如果个数最多的元素依然不多于字符串平均值,则说明一定符合要求,否则便不符合要求。在移动之前先初始化左,右指针的位置于第一个元素的位置,并计算出初始化的数组是否已经符合条件,若符合则无需再做判断;若不符合则进入循环判断。

代码

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s;
	cin>>s;
	char letter[4]={'Q','W','E','R'};
	int sum[4]={0};//四种字符个数的数量
	    
	int l=0,r=0;//尺取法的左右端点
	int n=s.size();
	for(int i=0;i<n;i++)
	{
		if(s[i]=='Q') sum[0]++;
		if(s[i]=='W') sum[1]++;
		if(s[i]=='E') sum[2]++;
		if(s[i]=='R') sum[3]++;
	}
	if(sum[0]==sum[1]&& sum[0]==sum[2]&& sum[0]==sum[3])
    {
    	cout<<0<<endl;
    	return 0;
	}
	for(int i=0;i<4;i++)
		if(s[0]==letter[i])
			sum[i]--;
	int ans=n-1;
	while(1<n)
	{
		int t1=max(sum[0],sum[1]);
		int t2=max(sum[2],sum[3]);
		int m=max(t1,t2);
		int total=r-l+1;
        if(m<=n/4)//一种更简单的判断方法,只要最大个数比平均个数少就可以平衡 
		{
			if(total<ans) ans=total;
			for(int i=0;i<4;i++)//修改剩下字母的个数 
			    if(s[l]==letter[i])
			        sum[i]++;
			l++;

		}
		else 
		{
			if(r==n-1) break;
			for(int i=0;i<4;i++)//修改剩下字母的个数
			    if(s[r+1]==letter[i])
			        sum[i]--;
			r++;

		}
	}
	cout<<ans<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值