【前缀和】平衡字符串

题面

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

Input

一行字符表示给定的字符串s(length<=105且 mod 4=0)。

Output

一个整数表示答案

Examples

Input

QWER

Output

0

Input

QQWE

Output

1

Input

QQQW

Output

2

Input

QQQQ

Output

3

思路

有一个明显的贪心,不管元素连不连续,要尽可能替换更少的元素,那么我们要找到不得不替换的元素,即只要把多于平均数的元素,替换成缺少的元素就可以。可以证明替换其他元素是无意义的。所以我们先求出需要替换的元素和个数。
对于一个搜素范围[l,r],求出其中每种可替换元素的数目,若大于等于相应种类的所需元素。说明搜索范围比较大,右边界右移。否则,左边界右移。
为了快速求解每个区间里元素数目,采用前缀和优化。可以获得均摊 O ( 1 ) O(1) O(1)的复杂度

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<map>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define mem(a,s) memset(a,s,sizeof(a))
map<char,int> m;
int n;
int a[100010];
int tt[4];
int sum[100010][4]; 
int main(){
//	freopen("1.txt","r",stdin);
	m['Q']=0;m['W']=1;
	m['E']=2;m['R']=3;
	string s;
	mem(sum,0);mem(tt,0);
	cin>>s; 
	rep(i,0,s.size()-1){//读入,QWER求数量  
		a[++n]=m[s[i]];
		tt[a[n]]++;
	}
	int avg=n/4;
	rep(i,0,3)//求与目标元素的差 
		tt[i]-=avg;
	rep(x,0,3)//求前缀和 
		rep(i,1,n){
			sum[i][x]=sum[i-1][x];
			if(a[i]==x)
				sum[i][x]++; 
		}
	int l=1,r=0;//特殊情况ans=0 
	int ans=1e5;
	while(l<=n&&r<=n){
		bool pd=true;
		rep(i,0,3)//区间内QWER元素要大于等于需要修改的元素 
			if((sum[r][i]-sum[l-1][i])<tt[i]){
				pd=false;break;
			}
		if(pd){//满足 
			int d=r-l+1;
			ans=min(ans,d);
			l++;
		}else r++;
	} 
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值