Codeforces 1196D2-RGB Substring (hard version)【前缀和】

题目链接

题意

有一个无限长的字符串“RGBRGBRGB……”,现在给你一个长度为n的字符串,字符全由RGB三种大写字母组成,再给出一个整数k,可以修改给出的字符串的任意字符,问最少需要修改几个字符才能找到一个长度为k的子串是无限字符串的子串。

思路

对原字符串的修改有三种情况,分别是开头为R,G,B的三种,即RGBRGB……,GBRGBR……,BRGBRG……,我们开三个前缀和数组记录三种字符为开头的前缀需要修改的字符个数,当 i 大于 k 是,就每次减去sum[i-k],得到 [ i-k,i ] 区间这三种情况需要修改几个字符,记录三种情况的最小值,最后取这三种的最小值即可;

代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
 
char s1[10] = "RGB", s2[10] = "GBR", s3[10] = "BRG", s[200200];
int sum1[200200], sum2[200200], sum3[200200];
 
int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		sum1[0] = 0;
		sum2[0] = 0;
		sum3[0] = 0;
		int n, k, ans1 = inf, ans2 = inf, ans3 = inf;
		scanf("%d%d%s", &n, &k, &s);
		for(int i = 0; i < n; i++){
			if(i != 0){
				sum1[i] = sum1[i-1];
				sum2[i] = sum2[i-1];
				sum3[i] = sum3[i-1];
			}
			if(s[i] != s1[i%3]){
				sum1[i]++;
			}
			if(s[i] != s2[i%3]){
				sum2[i]++;
			}
			if(s[i] != s3[i%3]){
				sum3[i]++;
			}
			if(i == k - 1){
				ans1 = sum1[i];
				ans2 = sum2[i];
				ans3 = sum3[i];
			}
			else if(i >= k){
				ans1 = min(ans1, sum1[i] - sum1[i - k]);
				ans2 = min(ans2, sum2[i] - sum2[i - k]);
				ans3 = min(ans3, sum3[i] - sum3[i - k]);
			}
		}
		ans1 = min(ans1, ans2);
		ans1 = min(ans1, ans3);
		printf("%d\n", ans1);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值