題目入口
解法:
這個題還有一個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;
}