week5作业——C:平衡字符串

主要思路:

尺取法的两个应用特征:寻找序列中满足要求的连续区间、有一定的方向性
显然本题满足这两个条件:要求替换一段连续的区域,需要从左向右地检查每个子区间,于是可以应用尺取法。
值得注意的是,进行了字符替换后,我们不能减少字符的数量,于是我们需要记录除掉当前区间剩余的部分中各个字符的数量(在本题有四个字符,分别记为sum1、sum2、sum3、sum4),若是有大于n/4的字符,那么这个区间显然是不合法的;也就是说,区间外与平衡字符串的差距是可以通过区间内的字符变动来弥补的,并且弥补后剩下的字符也必须符合平衡字符串的要求,这两点要求缺一不可
遇到满足条件的区间便立即更新答案

注意

需要将已经平衡了的字符串特判

C - 平衡字符串

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

Input

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

Output

一个整数表示答案

Sample Input

QQQW

Sample Output

2

A Possible Solution

#include<stdio.h>

const int N=1e5+5;
char s[N],letter[4]={'Q','W','E','R'};
int sum[4]={0},n=0;
//0 1 2 3 --- Q W E R 

int main(){
	scanf("%s",s);

	for(int i=0;s[i]!='\0';i++){
		n++;
		if(s[i]=='Q')sum[0]++;
		else if(s[i]=='W')sum[1]++;
		else if(s[i]=='E')sum[2]++;
		else if(s[i]=='R')sum[3]++;
	}
	
	if(sum[0]==sum[1] && sum[1]==sum[2] && sum[2]==sum[3]){
		printf("0\n");
		return 0;
	}
	
	int l=0,r=0,ans=n+1;
	int LRsum[4]={0};
	if(s[0]=='Q')LRsum[0]++;
	else if(s[0]=='W')LRsum[1]++;
	else if(s[0]=='E')LRsum[2]++;
	else if(s[0]=='R')LRsum[3]++;
	while(r<n){
		
		int maxx=(sum[0]-LRsum[0])>(sum[1]-LRsum[1])?(sum[0]-LRsum[0]):(sum[1]-LRsum[1]);
		maxx=maxx>(sum[2]-LRsum[2])?maxx:(sum[2]-LRsum[2]);
		maxx=maxx>(sum[3]-LRsum[3])?maxx:(sum[3]-LRsum[3]);
		int total=r-l+1,left;
		left=total-((maxx-sum[0]+LRsum[0])+(maxx-sum[1]+LRsum[1])+(maxx-sum[2]+LRsum[2])+(maxx-sum[3]+LRsum[3]));
		
		if(left>=0 && left%4==0){
			ans=ans<total?ans:total;
			l++;
			if(s[l-1]=='Q')LRsum[0]--;
			else if(s[l-1]=='W')LRsum[1]--;
			else if(s[l-1]=='E')LRsum[2]--;
			else if(s[l-1]=='R')LRsum[3]--;
			if(l==r+1){
				r++;//printf("r++ l++\n");
				if(s[r]=='Q')LRsum[0]++;
				else if(s[r]=='W')LRsum[1]++;
				else if(s[r]=='E')LRsum[2]++;
				else if(s[r]=='R')LRsum[3]++;
			}//else printf("l++\n");
		}
		else{
			r++;//printf("r++\n");
			if(s[r]=='Q')LRsum[0]++;
			if(s[r]=='W')LRsum[1]++;
			if(s[r]=='E')LRsum[2]++;
			if(s[r]=='R')LRsum[3]++;
		}
		
	}
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值