题意:
一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。
如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?
如果 s 已经平衡则输出0。
思路:对每个左端点找到合适的右端点确定合适区间,并对最小区间进行及时更新。因为需要平衡字符串,所以在[L,R]之外的Q,W,E,R个数进行计算,首先保证QWER都能达到四者中的最大值,所以[L,R]减去填充的长度后需要>=0&&剩下的%4==0,该过程快速求的一段区间内Q,W,E,R元素个数,可以用前缀和将o(n)降到o(1)
总结:
//尺取
//结果是针对于一段连续的区间,而且区间的变化方向是固定的
//每个左端点L能遍历到区间中的所有点
有两个指针l r,判断条件,当符合条件时l++,更新最小区间,当不符合时,r++找到符合区间继续更新最小区间
,这个过程遍历了所以左端点,并对每个左端点对应的小区间进行了遍历,最小区间在该过程中会被更新记录。
先举一个小栗子进行理解:
//求取区间和>=s 的最小区间(部分代码)
int l=1;r=0;
while(r<=n)
{
while(l<=r&&temp>=s) //满足l++条件
{
ans=min(ans,r-l+1);
temp=temp-a[l];
l++;
}
r++;
temp=temp+a[r];
}
代码:
题解:
//Q W E R n/4
//找最小区间使得改变和 四者相等
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int sum1[100010];
int sum2[100010];
int sum3[100010];
int sum4[100010];
char str[100010];
int main()
{
scanf("%s",str+1);// 'Q', 'W', 'E', 'R'
sum1[0]=0;sum2[0]=0;sum3[0]=0;sum4[0]=0;
for(int i=1;i<=strlen(str+1);i++)
{
if(str[i]=='Q')
{
sum1[i]=sum1[i-1]+1;//前缀和 快速求取一段区间内的某个元素的个数 (快速求取一段区间和)
sum2[i]=sum2[i-1];
sum3[i]=sum3[i-1];
sum4[i]=sum4[i-1];
}
if(str[i]=='W')
{
sum2[i]=sum2[i-1]+1;
sum1[i]=sum1[i-1];
sum3[i]=sum3[i-1];
sum4[i]=sum4[i-1];
}
if(str[i]=='E')
{
sum3[i]=sum3[i-1]+1;
sum1[i]=sum1[i-1];
sum2[i]=sum2[i-1];
sum4[i]=sum4[i-1];
}
if(str[i]=='R')
{
sum4[i]=sum4[i-1]+1;
sum1[i]=sum1[i-1];
sum2[i]=sum2[i-1];
sum3[i]=sum3[i-1];
}
}
if(sum1[strlen(str+1)]==strlen(str+1)/4&&sum2[strlen(str+1)]==strlen(str+1)/4&&sum3[strlen(str+1)]==strlen(str+1)/4&&sum4[strlen(str+1)]==strlen(str+1)/4)
{
cout<<0<<endl;exit(0);
}
int l=1;int r=0;int ans=100010;int tot;int sm1,sm2,sm3,sm4;
while(r<=strlen(str+1))
{
while(l<=r&&tot>=0&&tot%4==0)
{
ans=min(ans,r-l+1);//cout<<ans;
l++;
sm1=sum1[strlen(str+1)]-(sum1[r]-sum1[l-1]);
sm2=sum2[strlen(str+1)]-(sum2[r]-sum2[l-1]);
sm3=sum3[strlen(str+1)]-(sum3[r]-sum3[l-1]);
sm4=sum4[strlen(str+1)]-(sum4[r]-sum4[l-1]);
int mmax=max(max(sm1,sm2),max(sm3,sm4));
tot=r-l+1; tot=tot-((mmax-sm1)+(mmax-sm2)+(mmax-sm3)+(mmax-sm4));
}
r++;
sm1=sum1[strlen(str+1)]-(sum1[r]-sum1[l-1]);
sm2=sum2[strlen(str+1)]-(sum2[r]-sum2[l-1]);
sm3=sum3[strlen(str+1)]-(sum3[r]-sum3[l-1]);
sm4=sum4[strlen(str+1)]-(sum4[r]-sum4[l-1]);
int mmax=max(max(sm1,sm2),max(sm3,sm4));
tot=r-l+1; tot=tot-((mmax-sm1)+(mmax-sm2)+(mmax-sm3)+(mmax-sm4));
}cout<<ans<<endl;return 0;
}