You are given a string s consisting of n characters, each character is ‘R’, ‘G’ or ‘B’.
You are also given an integer k. Your task is to change the minimum number of characters in the initial string s so that after the changes there will be a string of length k that is a substring of s, and is also a substring of the infinite string “RGBRGBRGB …”.
A string a is a substring of string b if there exists a positive integer i such that a1=bi, a2=bi+1, a3=bi+2, …, a|a|=bi+|a|−1. For example, strings “GBRG”, “B”, “BR” are substrings of the infinite string “RGBRGBRGB …” while “GR”, “RGR” and “GGG” are not.
You have to answer q independent queries.
Input
The first line of the input contains one integer q (1≤q≤2⋅105) — the number of queries. Then q queries follow.
The first line of the query contains two integers n and k (1≤k≤n≤2⋅105) — the length of the string s and the length of the substring.
The second line of the query contains a string s consisting of n characters ‘R’, ‘G’ and ‘B’.
It is guaranteed that the sum of n over all queries does not exceed 2⋅105 (∑n≤2⋅105).
Output
For each query print one integer — the minimum number of characters you need to change in the initial string s so that after changing there will be a substring of length k in s that is also a substring of the infinite string “RGBRGBRGB …”.
3
5 2
BGGGG
5 3
RBRGR
5 5
BBBRR
1
0
3
先给出代码:
#include<bits/stdc++.h>
using namespace std;
int q,n,k;
string s;
char jh[3]={'R','G','B'}; //比对时用
int f[200005];
int main(){
cin>>q;
for(int i=0;i<q;i++){
cin>>n>>k;
cin>>s;
int ans=300000; //赋个极大值,遇到比ans小的值就更新ans
for(int j=0;j<3;j++){ //枚举开头可能为三种颜色,因开头可能也需要变
int flag=j; //用于记录RGB的顺序
int cnt=0;
for(int x=0;x<n;x++){ //按照RGB的顺序一个一个比对
f[x]=(s[x]!=jh[flag]); //记录每一位是否需要变化,0为不用1为用
if(f[x]){
cnt+=f[x]; //记录总消费
}
flag++;
flag%=3;
if(x>=k){ //到达k位时已选取k+1个,需要每次减去最前面的消耗
cnt-=f[x-k]; //需在更新前,防止多算一位的消耗
}
if(x>=k-1){
ans=min(ans,cnt);//遇到比ans小的值就更新ans
//前提是已经到k-1位,这样已经选取了k个数了
}
}
}
cout<<ans<<endl;
}
return 0;
}
首先,我们的思路是在n个字符中,挪动k长度的区间,通过变量记录更新最小值
当然,我们需要先确定RGB的顺序,可以是RGBRGB…也可以是GBRGBR…或者BRGBRG…我们无法确定哪个更优,消耗更小,因此枚举三种可能的顺序
用数组记录每一位是否符合我们枚举的顺序,并将其累加,当长度到达k时,便可以不断更新我们的ans值了,取最小的,当然长度为k+1时需要减去最前面的那位的消耗,因为区间类似于在整体移动,往后走了一位,前面就要减去一位,因为题目要求的是找一个连续区间长度为k的符合RGB顺序的区间,更改正确所需要的最小消耗
这样时间就为3*n,时间复杂度就只有O(n)