版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
题意:
一个无限长的b字符串为"RGBRGB…", 现在给你一个字符串a,你可以对字符串的任意一个字符进行修改,问最少修改次数使a,b的最长公共字串长度为k。
题解:
在D1中字符串a长度最长仅为2000,因此可以遍历修改后满足a,b的最长公共字串长度为k的所有情况,维护最小次数sum即可。时间复杂度为O(nk).
PS:由于字符串a仅由’R’,‘G’,'B’构成,因此当k=1时sum = 0。
//
//Write by Yuan Xilan on 2019...
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const int inf = 0x3f3f3f3f;
const int maxn = 1e+5;
char s[2020];
char s1[] = {'R','G','B'};
int main(int argc, char * argv[])
{
std::ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--){
int n,k;
cin >> n >> k;
cin >> s;
bool flag = true;
if(k == 1){
for(int i=0; i<n; ++i){
if(s[i] == 'R' || s[i] == 'G' || s[i] == 'B') cout << 0 << endl;
flag = false;
break;
}
if(flag){
cout << 1 << endl;
}
continue;
}
int minn = inf;
for(int i=0; i+k<=n; ++i){
char p = s[i];
for(int q = 0; q < 3; ++q){
int sum = 0;
s[i] = s1[q];
if(p != s1[q]) sum += 1;
if(s[i] == 'B'){
for(int j=i+1; j<=i+k-1; ++j){
if((j - i - 1) % 3 == 0){
if(s[j] != 'R'){
sum += 1;
}
}
else if((j - i - 1) % 3 == 1){
if(s[j] != 'G') sum += 1;
}
else if((j - i - 1) % 3 == 2) if(s[j] != 'B') sum += 1;
}
//cout << sum << endl;
}
else if(s[i] == 'R'){
for(int j=i+1; j<=i+k-1; ++j){
if((j - i - 1) % 3 == 0){
if(s[j] != 'G'){
sum += 1;
}
}
else if((j - i - 1) % 3 == 1){
if(s[j] != 'B') sum += 1;
}
else if((j - i - 1) % 3 == 2) if(s[j] != 'R') sum += 1;
}
}
else if(s[i] == 'G'){
for(int j=i+1; j<=i+k-1; ++j){
if((j - i - 1) % 3 == 0){
if(s[j] != 'B'){
sum += 1;
}
}
else if((j - i - 1) % 3 == 1){
if(s[j] != 'R') sum += 1;
}
else if((j - i - 1) % 3 == 2) if(s[j] != 'G') sum += 1;
}
}
minn = min(minn,sum);
}
}
cout << minn << endl;
}
return 0;
}
当n,k均为2e5时,可以改用以下思路:
pre[i]数组记录字符串a从下标从1到i逐个修改,使a,b的最长公共字串长度为i的次数,可用前缀和记录,时间复杂度为O(n)。
//
//Write by Yuan Xilan on 2019...
//
#include <bits/stdc++.h>
using namespace std;
const char str[] = "RGB";
const int maxn = 2e5+5;
const int inf = 0x3f3f3f3f;
char s[maxn];
int pre[maxn];
int main(){
int t,n,k;
scanf("%d",&t);
int minn;
while(t--){
scanf("%d%d",&n,&k);
scanf("%s",s+1);
minn = inf;
for(int i=0; i<3; ++i){
for(int j=1; j<=n; ++j){
if(s[j] != str[(i+j)%3]) pre[j] = 1;
else pre[j] = 0;
}
for(int j=1; j<=n; ++j){
pre[j] += pre[j-1];
}
for(int j=k; j<=n; ++j){
minn = min(minn,pre[j] - pre[j-k]);
}
}
printf("%d\n",minn);
}
}