第一行两个整数 n , m (1<=m<=n<=50000),第二行为长度为n且只包含’a’和’b’的字符串s。
输出在操作次数不超过 m 的情况下,能够得到的 最大连续 全’a’子串或全’b’子串的长度。
8 1 aabaabaa
5
把第一个 'b' 或者第二个 'b' 置成 'a',可得到长度为 5 的全 'a' 子串。
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] strs1=br.readLine().split(" ");
int n=Integer.parseInt(strs1[0]);
int m=Integer.parseInt(strs1[1]);
String s=br.readLine();
int[] A=new int[n];
int[] B=new int[n];
A[0]=s.charAt(0)=='a'?1:0;
B[0]=s.charAt(0)=='b'?1:0;
for(int i=1;i<n;i++){
if(s.charAt(i)=='a'){
A[i]=A[i-1]+1;
B[i]=B[i-1];
}else{
B[i]=B[i-1]+1;
A[i]=A[i-1];
}
}
int max=0;
for(int k=0;k<n;k++){
int i=0;
int j=k;
if(s.charAt(k)=='a'){
while(i<j){
int mid=i+(j-i)/2;
if(func(B,mid,k,m)) j=mid;
else i=mid+1;
}
}else{
while(i<j){
int mid=i+(j-i)/2;
if(func(A,mid,k,m)) j=mid;
else i=mid+1;
}
}
max=Math.max(max,k-i+1);
}
System.out.println(max);
}
public static boolean func(int[] dp,int i,int j,int m){
if(i==0){
return dp[j]<=m;
}else{
return dp[j]-dp[i-1]<=m;
}
}
}
前缀和+二分,时间复杂度O(NlogN)
// 滑动窗口 +队列记录
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while(in.hasNext()){
int n = in.nextInt();
int m = in.nextInt();
String str = in.next();
int max = Math.max(getMax(str,'a',m),getMax(str,'b',m));
System.out.println(max);
}
}
// 统计变a和变b的最长长度
public static int getMax(String str,char ch,int count){
int max = 0;
LinkedList ll = new LinkedList(); // 用于记录需要变换的字符的下标
int len = str.length();
int d = 0; // 窗口的大小
for ( int i = 0; i < len; ++i ) {
if (str.charAt(i) == ch) {
d++; // 不需替换的字符 窗口直接增大
}else {
if (count > 0) { // 需替换的字符且有剩余替换次数 窗口增大 次数减少1
d++;
count--;
}else { // 需替换的字符且没有剩余替换次数 则取出最左边被替换的字符的下标(index) 同时重新计算窗口大小[i-index]
int index = (int)ll.poll();
d = i - index;
}
ll.add(i); // 记录需要替换字符的下标
}
max = Math.max(d,max);
}
return max;
}
} //时间复杂度o(n),使用滑动窗口的思想,维持左指针和右指针,窗口大小为反转次数用完后a或b的最大长度。
#include<vector>
#include<string>
#include<iostream>
using namespace std;
int inverse(string& str,int dept,char target){
int left=0,right=-1,max_len=0,times=0;
for(int i=0;i<str.size();i++){
right++;
if(str[i]!=target){
times++;
if(times>dept){
max_len=max(max_len,right-left);
while(left!=right && str[left]==target){
left++;
}
if(str[left]!=target){
left++;
times--;
}
}
}
}
return max_len;
}
int main(){
int lenght,dept;
cin>>lenght>>dept;
string str;
cin>>str;
int max_a=inverse(str,dept,'a');
int max_b=inverse(str,dept,'b');
cout<<max(max_a,max_b);
return 0;
} static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
int n = sc.nextInt();
int m = sc.nextInt();
sc.nextLine();//吃空格
String s = sc.nextLine();
System.out.println(fun(s.toCharArray(),m));
}
static private int fun(char[] chars,int k){
int res=0;
int len = chars.length;
int right=0,left=0;
int[] window = new int[2];
while (right<len){
char cur = chars[right];
window[cur-'a']++;
res=Math.max(window[cur-'a'],res);//最大字母的出现次数
while (res+k<right-left+1){
window[chars[left]-'a']--;
left++;
}
right++;
}
return len-left;
} import java.util.List;
import java.util.ArrayList;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] strs1=br.readLine().split(" ");
int n=Integer.parseInt(strs1[0]);
int m=Integer.parseInt(strs1[1]);
String s=br.readLine();
int res = 0;
List<Integer> aList = new ArrayList<>();
List<Integer> bList = new ArrayList<>();
aList.add(-1);
bList.add(-1);
for(int i=0;i<n;i++){
if(s.charAt(i)=='a')aList.add(i);
else bList.add(i);
}
aList.add(n);
bList.add(n);
for(int i=1;i<aList.size()- m;i++){
int j = i+m-1;
int t = aList.get(j+1) - aList.get(i-1)-1;
if(t >res)res = t;
}
for(int i=1;i<bList.size()-m ;i++){
int j = i+m-1;
int t = bList.get(j+1) - bList.get(i-1)-1;
if(t >res)res = t;
}
System.out.print(res);
}
}
#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
string str;
cin>>str;
//全A的情况
int dpa[50001] = {0};
if(str[0] == 'a'){
for(int i=0;i<=m;i++){
if(i%2 == 0)
dpa[i] = 1;
else
dpa[i] = 0;
}
}else{
for(int i=0;i<m;i++){
if(i%2 == 0)
dpa[i] = 0;
else
dpa[i] = 1;
}
}
int maxa=0;
for(int i=2;i<=n;i++){
for(int j = m;j>=0;j--){
if(str[i-1] == 'a'){
dpa[j] = dpa[j]+1;
}else{
if(j>=1){
dpa[j] = dpa[j-1]+1;
}else{
dpa[j] = 0;
}
}
if(dpa[j]>maxa){
maxa = dpa[j];
}
if(maxa == n)
break;
// printf("dpa[%d][%d] = %d\n",i,j,dpa[i][j]);
}
if(maxa == n)
break;
}
int maxb=0;
//全B的情况
if(maxa<=n-maxa){
int dpb[50001] = {0};
if(str[0] == 'a'){
for(int i=0;i<m;i++){
if(i%2 == 0)
dpb[i] = 0;
else
dpb[i] = 1;
}
}else{
for(int i=0;i<=m;i++){
if(i%2 == 0)
dpb[i] = 1;
else
dpb[i] = 0;
}
}
for(int i=2;i<=n;i++){
for(int j = m;j>=0;j--){
if(str[i-1] == 'b'){
dpb[j] = dpb[j]+1;
}else{
if(j>=1){
dpb[j] = dpb[j-1]+1;
}else{
dpb[j] = 0;
}
}
if(dpb[j]>maxb){
maxb = dpb[j];
}
if(maxb == n)
break;
}
if(maxb == n)
break;
}
}
printf("%d",max(maxa,maxb));
return 0;
}
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int n,m;
int countt[50005]={0};
int ans = 0;
bool check(int len){
for(int i=0;i<n-len+1;i++){
int cnta = countt[i+len-1]-countt[i-1];
int cntb = len-cnta;
if(min(cnta,cntb)<=m){
return true;
}
}
return false;
}
int main(){
cin>>n>>m;
string str;
cin>>str;
int h = 0;
for(int i=0;i<n;i++){
if(str[i]=='a'){
h = h+1;
countt[i] = h;
}else
countt[i] = h;
}
int right = n,left = 1,mid;
while(left<=right){
mid = left+(right-left)/2;
if(check(mid)){
left = mid+1;
}
else{
right = mid-1 ;
}
}
printf("%d\n",right);
return 0;
} 要注意二分边界的处理,最后要返回的是右边界,左边界不可以。