这道题是字节21年算法方向的编程题。原题如下:
子串长度
时间限制: 1000MS 内存限制: 65536KB
题目描述:
有一个仅包含’a’和’b’两种字符的字符串s,长度为n,每次操作可以把一个字符做一次转换(把一个’a’设置为’b’,或者把一个’b’置成’a’);但是操作的次数有上限m,问在有限的操作数范围内,能够得到最大连续的相同字符的子串的长度是多少。
输入描述
第一行两个整数 n , m (1<=m<=n<=50000),第二行为长度为n且只包含’a’和’b’的字符串s。
输出描述
输出在操作次数不超过 m 的情况下,能够得到的 最大连续 全’a’子串或全’b’子串的长度。
样例输入
8 1 aabaabaa
样例输出
5
其实这道题并不难,但是我没看出来做题的思路,在那里用回溯做,复杂度又高,一顿操作就过了66%。这道题用双指针就可以了,和之前的双指针题目是一个类型,只用维护好a_cnt
和b_cnt
就可以,当a_cnt
或者b_cnt
小于m
时直接进行翻转可以保证当前字符串全部翻转成一样。只有当两者都超过m
时才需要移动left
。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
string s;
cin>>s;
int left=0, right=0;
int a_cnt=0, b_cnt=0;
int res=0;
while(right<n){
if(s[right]=='a'){
a_cnt++;
}
else{
b_cnt++;
}
if(a_cnt>m&&b_cnt>m){
if(s[right]=='a'){
while(s[left]=='b'){
++left;
b_cnt--;
}
++left;
a_cnt--;
}
else{
while(s[left]=='a'){
++left;
a_cnt--;
}
++left;
b_cnt--;
}
}
res=max(res,right-left+1);
++right;
}
cout<<res<<endl;
}