开 始 脑 子 太 笨 了 , 没 想 到 D P 的 做 法 开始脑子太笨了,没想到DP的做法 开始脑子太笨了,没想到DP的做法
但 是 发 现 可 以 预 处 理 出 这 样 一 个 数 组 但是发现可以预处理出这样一个数组 但是发现可以预处理出这样一个数组
以 i 开 头 到 末 尾 中 , 字 符 R 位 置 在 第 1 , 第 2 , 第 3 出 现 的 次 数 ( 3 次 一 循 环 ) 以i开头到末尾中,字符R位置在第1,第2,第3出现的次数(3次一循环) 以i开头到末尾中,字符R位置在第1,第2,第3出现的次数(3次一循环)
R R R R RRRR RRRR
比 如 上 面 这 个 串 , 1 和 4 位 置 都 是 R , 所 以 R 在 第 1 出 现 了 2 次 比如上面这个串,1和4位置都是R,所以R在第1出现了2次 比如上面这个串,1和4位置都是R,所以R在第1出现了2次
同 样 处 理 出 G 和 B 的 数 据 同样处理出G和B的数据 同样处理出G和B的数据
那 么 加 入 按 照 R G B 循 环 , 选 取 [ i , i + k − 1 ] 区 间 最 为 答 案 那么加入按照RGB循环,选取[i,i+k-1]区间最为答案 那么加入按照RGB循环,选取[i,i+k−1]区间最为答案
那 么 R 字 符 第 一 次 出 现 的 位 置 对 上 , G 第 二 次 出 现 位 置 对 上 , B 第 三 次 出 现 位 置 对 上 那么R字符第一次出现的位置对上,G第二次出现位置对上,B第三次出现位置对上 那么R字符第一次出现的位置对上,G第二次出现位置对上,B第三次出现位置对上
没 有 对 上 的 就 不 能 作 为 答 案 没有对上的就不能作为答案 没有对上的就不能作为答案
#include <bits/stdc++.h>
using namespace std;
int n,k,ls,dp[200009][4][4];
char s[200009];
void er(int &q)
{
if(q==3) q=1;
else if(q==2) q=3;
else q=2;
}
void yi(int &q)
{
if(q==1) q=3;
else if(q==2) q=1;
else q=2;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>k>>(s+1);
ls=strlen(s+1);
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++) dp[ls+1][i][j]=0;
for(int i=ls;i>=1;i--)
{
for(int j=1;j<=3;j++)
{
int last=j-1;
if(j==1) last=3;
dp[i][1][j]=dp[i+1][1][last];
dp[i][2][j]=dp[i+1][2][last];
dp[i][3][j]=dp[i+1][3][last];
}
if(s[i]=='R') dp[i][1][1]++;
else if(s[i]=='G') dp[i][2][1]++;
else if(s[i]=='B') dp[i][3][1]++;
}
int ans=1e9;
for(int i=1;i+k-1<=ls;i++)
{
int r=i+k-1;
for(int j=1;j<=3;j++)
{
int e=j,q=j+1,w=j+2,xi=k%3;
if(q>3) q-=3;
if(w>3) w-=3;
int now=dp[i][1][e]+dp[i][2][q]+dp[i][3][w];
if(xi==1) yi(e),yi(q),yi(w);
else if(xi==2) er(e),er(q),er(w);
now-=(dp[r+1][1][e]+dp[r+1][2][q]+dp[r+1][3][w]);
ans=min(ans,k-now);
}
}
cout<<ans<<endl;
}
}