week5 C - 平衡字符串(尺取法)

一、题目描述

一个长度为 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

Note

1<=n<=10^5
n是4的倍数
字符串中仅包含字符 ‘Q’, ‘W’, ‘E’ 和 ‘R’.

二、思路概述
1.用sum[4]数组来记录QWER四个字母在[l,r]范围外的数量;
2.初始时l=r=0,每次判断区间[l,r]是否满足条件(条件为total=r-l+1;
free=total-(maxsum-sum[0])-(maxsum-sum[1])-(maxsum-sum[2])-(maxsum-sum[3]);
free>=0且free为4的倍数);若满足条件,若r==l,则l++,r++,否则l++即可,并更新sum的值,若不满足条件,r++,并更新sum.

三、细节
1.又把l++,和++l搞混了,忘记到底怎么样使用才正确,就错了,真的是,要么不用了,要么就要记好使用方法。
2.由于sum的初始值是字符串中各个字符的个数,l和r初始时都是1,此时的sum就需要被更新,而我忘了这一点,就导致了错误。

四、完整代码

#include<iostream>
#include<string.h>
#include<map>
#include<math.h>
#include <algorithm> 
using namespace std;

map<char,int> mp;
int main()
{
	//给mp数组赋值,将字母跟数字对应 
	char s[4];
	strcpy(s,"QWER");
	for(int i=0;i<4;i++)
	{
	 mp[s[i]]=i;
	}
	
	//初始数据处理	
    char str[1000000];
    cin>>str;
    int num=0;
    int sum[4];
    fill(sum,sum+4,0);
    char c;
    for(int i=0;str[i]!='\0';i++)
	{
		num++;
		c=str[i];
		sum[mp[c]]++;	
	}
   // cout<<num<<endl;
    //计算 
	int l=0;//l和r在最开始的时候,都是0,表示从数组开头开始 
	int r=0;
	int ans=num;
	int total,free,maxsum=0;
	if(sum[0]==num/4&&sum[1]==num/4&&sum[2]==num/4&&sum[3]==num/4)
	ans=0; 
	else
	{	
	sum[mp[str[0]]]=sum[mp[str[0]]]-1;

	while(r!=num) 
	{
		//计算此时maxsum、total、free的值 
		maxsum=sum[0];		
		for(int i=1;i<4;i++)
		{
			if(sum[i]>maxsum)maxsum=sum[i];
		}
		total=r-l+1;
		free=total-(maxsum-sum[0])-(maxsum-sum[1])-(maxsum-sum[2])-(maxsum-sum[3]);
	    //cout<<l<<" "<<r<<" "<<total<<" "<<free<<" "<<maxsum<<endl;
		//判断此时是否满足条件 
		if(free>=0&&free%4==0)
		{
			if(total<ans)ans=total;
			
			//若r=l,则l++,r++ 
			if(r==l)
			{
			    int ll=mp[str[l]];
			    sum[ll]++;
				l++;
				
				r=r+1;
		   	    int rr=mp[str[r]];
		   	    sum[rr]--;
			}
			//若r!=l则l++ 
			else 
			{			    
			    int ll=mp[str[l]];//前++和后++,啊啊啊啊啊 
			    sum[ll]++;
				l++;
			}
		}
		//不满足条件的时候,r++即可 
		else
		{
		   	r=r+1;
		   	int rr=mp[str[r]];
		   	sum[rr]--;
		} 
	}
    }
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值