一、题目描述
一个长度为 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;
}