题目入口
解法:
这个题还有一个easy版本的。
1. 首先应该知道怎么计算替换次数:因为要保持顺序,所以只要将长度相同的两个串进行对应位置一一对比,不相同的就计数,之后比较计数最小的就行了。
2. 拿什么比较?因为是RGBGB...依次循环下去的,所以我们只要枚举开头的字母,一共是三种情况:RGB.../GBR.../BRG...,即可。
3. 优化:如果每次将原串中长度为K的子串挑选出来进行比较,则这种做法比较低效,TLE在所难免。这里可以忽略K值,我们利用前缀和的思想,sum[i][j]代表第i中情况(前面说的三种开头字母的情况),j表示字符串S中前j个字符需要调整的次数。如何迭代sum参照代码。
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define INF 0x3f3f3f3f
const int maxn=1e6+9;
int q,n,k,ans,sum[3][maxn];
string s,t="RGB";
int main()
{
scanf("%d",&q);
while(q--)
{
ans=INF;
scanf("%d%d",&n,&k);
cin>>s;
sum[0][0]=sum[1][0]=sum[2][0]=0;
for(int d=0;d<3;d++)
for(int i=1;i<=n;i++)
if(s[i-1]!=t[(d+i-1)%3])
sum[d][i]=sum[d][i-1]+1;
else
sum[d][i]=sum[d][i-1];
for(int d=0;d<3;d++)
for(int i=k;i<=n;i++)
ans=min(ans,sum[d][i]-sum[d][i-k]);
printf("%d\n",ans);
}
return 0;
}