题目:
一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。
如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?
如果 s 已经平衡则输出0。
输入:
一行字符表示给定的字符串s
输出:
一个整数表示答案
因为题目要求把连续字符串替换掉,所以可以用一个长度可变的移动窗口,先计算Q W E R各个字符的个数与4/n的差距,保存数组,然后根据窗口减去窗口内各个字符的个数,如果每个字符的个数均小于等于0,说明可以把窗口内的字符串合理分配,使得每个字符的个数都等于n/4,如果窗口外某个字符个数比n/4大,则不可能让4个字符都为n/4个。在可以使四个字符数目相同的情况下,记录窗口大小,将窗口左边界右移一位,以寻找更优解;如果不能,则将右边界右移一位,寻找可能的解,因为窗口越大,就越可能成功平衡字符串,如果窗口和字符串长度相同,则必定能平衡。
以下是完整代码:
#include<iostream>
#include<string>
#include<string.h>
using namespace std;
int trans(char ch)//将字符转换成想应的数字
{
if(ch=='Q') return 0;
if(ch=='W') return 1;
if(ch=='E') return 2;
if(ch=='R') return 3;
}
int min(int a,int b)
{
return a<b?a:b;
}
int main()
{
int count[4]={0,0,0,0};
string s;
cin>>s;
int len=s.length();
for(int i=0;i<len;i++)//为Q W E R计数
{
count[trans(s[i])]++;
}
int n=len/4;
bool balance=true;
for(int i=0;i<4;i++)//计算与n/4的差距
{
count[i]-=n;
if(count[i]!=0)
{
balance=false;
}
}
if(balance==true)//如果balance,说明初始就平衡
{
cout<<"0";
return 0;
}
int l=0,r=0;//左边界,右边界
int ans=500000;
while(l<=r&&r<len)
{
balance=true;
count[ trans( s[r] ) ]--;//右边界的字符在窗口外的数目减一
while(balance)
{
for(int i=0;i<4;i++)
{
if(count[i]>0)
{
balance=false;
break;
}
}
if(balance==true)
{
ans=min(ans,r-l+1);//保存更优答案
count[ trans(s[l]) ]++;
l++;
}
}
r++;
}
cout<<ans;
}