尺取法
使用尺取法的条件:
具体题目
一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。
如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?
如果 s 已经平衡则输出0。
分析
这道题使用尺取法的话需要分析,什么情况是满足条件的。
1、首先使用sum1,sum2,sum3,sum4记录在l,r之外的字符Q,W,E,R的个数
2、记:max=max(sum1,sum2,sum3,sum4)
3、那么(max-sum1)+(max-sum2)+(max-sum3)+(max-sum4)就是需要替换的字符才能得以平衡。
4、l-r+1这段字符减去要替换的字符个数,如果能被4整除,且大于等于0,那么就是满足条件。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char s[100001];
int main()
{
int sum1=0,sum2=0,sum3=0,sum4=0;
int l=0,r=0;
int flag=0;
scanf("%s",s);
int n=strlen(s);//获取长度
//初始化sum
for(int i=0;i<n;i++)
{
if(s[i]=='Q') sum1++;
else if(s[i]=='W') sum2++;
else if(s[i]=='E') sum3++;
else sum4++;
}
int num=n/4;
if(sum1==num&&sum2==num&&sum3==num&&sum4==num)
{
printf("0\n");
flag=1;
}
int ans=n;
while(r<n&&flag==0)
{
if(s[r]=='Q') sum1--;
else if(s[r]=='W') sum2--;
else if(s[r]=='E') sum3--;
else sum4--;
int themax=std::max(std::max(sum1,sum2),std::max(sum3,sum4));
int total=r-l+1;
int free=total-((themax-sum1)+(themax-sum2)+(themax-sum3)+(themax-sum4));
while (free>=0 && free%4==0)
{
if(ans>r-l+1)
ans=r-l+1;
if(s[l]=='Q') sum1++;
else if(s[l]=='W') sum2++;
else if(s[l]=='E') sum3++;
else sum4++;
l++; //移动左指针
themax=std::max(std::max(sum1,sum2),std::max(sum3,sum4));
total=r-l+1;
free=total-((themax-sum1)+(themax-sum2)+(themax-sum3)+(themax-sum4));
}
r++; //移动右指针
}
if(flag==0) printf("%d\n",ans);
return 0;
}