第一行两个整数 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; }要注意二分边界的处理,最后要返回的是右边界,左边界不可以。