week5 作业C 平衡字符串

平衡字符串

一个长度为 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

我的思路:
这道题要达到的目的,是通过替换字符串中的一段连续字符,来使得‘Q’ 、‘W’、 ‘E’、 'R’这四个字母在字符串中的个数相等,求能达到这个要求的最短连续字符的长度。我用的是尺取法,即设置两个指针,一个左端指针L和一个右端指针R,从最左端的第一个元素开始,计算这个区间外的四个字母个数,若当前区间可以达到将四个字母个数填充相等(即区间外的四个字母个数与其中最大个数的差距,用区间弥补,弥补过后若剩下的空余空间是4的倍数(或0),则满足条件),则将左指针向右移一个单位;否则,右指针向右移动一个单位。最后,统计满足条件的最短长度即可。

我的总结:
对于这种改变一段连续的区间,并求最短距离的问题,尺取法是一个很好的方法,在时间复杂度上要优于二分。

我的代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

string s;
long long ans,sum[4],MAX,tot,fre,L,R;

void su(long long idl,long long idr)
{
    for(long long i=0;i<4;i++) sum[i]=0;
    for(long long i=0;i<idl;i++)
    {
        if(int(s[i])==int('Q')) sum[0]++;
        if(int(s[i])==int('W')) sum[1]++;
        if(int(s[i])==int('E')) sum[2]++;
        if(int(s[i])==int('R')) sum[3]++;
    }
    
    for(long long i=idr+1;i<s.size();i++)
    {
        if(int(s[i])==int('Q')) sum[0]++;
        if(int(s[i])==int('W')) sum[1]++;
        if(int(s[i])==int('E')) sum[2]++;
        if(int(s[i])==int('R')) sum[3]++;
    }
}

long long jud()
{
    L=R=0;
    su(L,R); 
    while(L<s.size()&&R<s.size()&&L<=R)
    {
            MAX=max(max(sum[0],sum[1]),max(sum[2],sum[3]));
            tot=R-L+1;
            fre=tot-((MAX-sum[0])+(MAX-sum[1])+(MAX-sum[2])+(MAX-sum[3]));
            if(fre>=0&&fre%4==0)
            {
                ans=min(ans,R-L+1);
                if(int(s[L])==int('Q')) sum[0]++;
        		if(int(s[L])==int('W')) sum[1]++;
        		if(int(s[L])==int('E')) sum[2]++;
        		if(int(s[L])==int('R')) sum[3]++;
                L++;
            }
            else
            {
                R++;
                if(int(s[R])==int('Q')) sum[0]--;
        		if(int(s[R])==int('W')) sum[1]--;
        		if(int(s[R])==int('E')) sum[2]--;
        		if(int(s[R])==int('R')) sum[3]--;
            }
            
        }
        return ans;
}

int main()
{
    while(cin>>s)
    {
        su(0,-1);
        if(sum[0]==sum[1]&&sum[1]==sum[2]&&sum[2]==sum[3]) 
        {
            printf("0\n");
            continue;
        }
        ans=s.size();
        printf("%lld\n",jud());
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值