【Codeforces Round #575 (Div. 3) 】 RGB Substring (hard version) ( FFT)

D2. RGB Substring (hard version)

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

The only difference between easy and hard versions is the size of the input.

You are given a string ss consisting of nn characters, each character is ‘R‘, ‘G‘ or ‘B‘.

You are also given an integer kk. Your task is to change the minimum number of characters in the initial string ss so that after the changes there will be a string of length kk that is a substring of ss, and is also a substring of the infinite string "RGBRGBRGB ...".

A string aa is a substring of string bb if there exists a positive integer ii such that a1=bia1=bi, a2=bi+1a2=bi+1, a3=bi+2a3=bi+2, ..., a|a|=bi+|a|−1a|a|=bi+|a|−1. For example, strings "GBRG", "B", "BR" are substrings of the infinite string "RGBRGBRGB ..." while "GR", "RGR" and "GGG" are not.

You have to answer qq independent queries.

Input

The first line of the input contains one integer qq (1≤q≤2⋅1051≤q≤2⋅105) — the number of queries. Then qq queries follow.

The first line of the query contains two integers nn and kk (1≤k≤n≤2⋅1051≤k≤n≤2⋅105) — the length of the string ss and the length of the substring.

The second line of the query contains a string ss consisting of nn characters ‘R‘, ‘G‘ and ‘B‘.

It is guaranteed that the sum of nn over all queries does not exceed 2⋅1052⋅105 (∑n≤2⋅105∑n≤2⋅105).

Output

For each query print one integer — the minimum number of characters you need to change in the initial string ss so that after changing there will be a substring of length kk in ss that is also a substring of the infinite string "RGBRGBRGB ...".

Example

input

Copy

3
5 2
BGGGG
5 3
RBRGR
5 5
BBBRR

output

Copy

1
0
3

Note

In the first example, you can change the first character to ‘R‘ and obtain the substring "RG", or change the second character to ‘R‘ and obtain "BR", or change the third, fourth or fifth character to ‘B‘ and obtain "GB".

In the second example, the substring is "BRG".

SLUTION:

这题比赛的时候有两个版本,easy版的直接暴力看有多少配的的字符就行了

hard 版本的n到达了2e5,我们可以使用fft来优化字符匹配的过程 复杂度o(3*n*Logn)

CODE:

#include"bits/stdc++.h"
#define sd(x) scanf("%lf",&(x));
#define sld(x) scanf("%lld",&(x));
using namespace std;

const int maxn = 2e6+10;
const double Pi = acos(-1.0);

struct cp
{
    double x,y;
    cp (double xx=0,double yy=0)
    {
        x=xx,y=yy;
    }
} a[maxn],b[maxn];
cp operator + (cp a,cp b)
{
    return cp(a.x+b.x , a.y+b.y);
}
cp operator - (cp a,cp b)
{
    return cp(a.x-b.x , a.y-b.y);
}
cp operator * (cp a,cp b)
{
    return cp(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);   //不懂的看复数的运算那部分
}

int n,k;
int l,r[maxn];
int limit = 1;

inline void fft(cp *a,int ff)
{
    for(int i=0; i<limit; i++)
        if(i<r[i])swap(a[i],a[r[i]]);
    for(int mid=1; mid<limit; mid<<=1)
    {
        cp wn(cos(Pi/mid) , ff*sin(Pi/mid));
        for(int R=mid<<1,j=0; j<limit; j+=R)
        {
            cp w(1,0);
            for(int k=0; k<mid; k++,w=w*wn)
            {
                cp x=a[j+k],y=w*a[j+mid+k];
                a[j+k]=x+y;
                a[j+mid+k]=x-y;
            }
        }

    }

}
char s[2000000];
char t[2000000];
int tot;
int ans;
char ff[]= {‘R‘,‘G‘,‘B‘};
int tmp[2000000];
void work()
{
    int m=tot;
    limit=1;
    l=0;
    reverse(t,t+m);
    while(limit<=n+m)limit<<=1,l++;
    for(int i=0; i<limit; i++)
        r[i]=(r[i>>1]>>1)|( (i&1)<<(l-1));

    for(int j=m-1; j<m+n-k; j++) tmp[j]=0;

    for(int o=0; o<3; o++)
    {
        for(int j=0; j<limit; j++)a[j].x=a[j].y=b[j].x=b[j].y=0;
        for(int j=0; j<m; j++)a[j].x=(t[j]==ff[o]);
        for(int j=0; j<n; j++)b[j].x=(s[j]==ff[o]);
        fft(a,1);
        fft(b,1);
        for(int j=0; j<limit; j++)a[j]=a[j]*b[j];
        fft(a,-1);

        for(int j=m-1; j<m+n-k; j++)
            tmp[j] += int(a[j].x/limit + 0.5);

    }
    for(int j=m-1; j<m+n-k; j++)
        ans=min(ans,k-tmp[j]);

}

int main()
{

    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>k;
        cin>>s;
        ans=1e9;
        tot=k;
        for(int i=0; i<k; i++)
            t[i]=ff[(i)%3];
        work();
        for(int i=0; i<k; i++)
            t[i]=ff[(i+1)%3];
        work();
        for(int i=0; i<k; i++)
            t[i]=ff[(i+2)%3];
        work();
        cout<<ans<<endl;
    }
}

  

原文地址:https://www.cnblogs.com/zhangbuang/p/11242098.html

时间: 2024-08-30 02:13:59

【Codeforces Round #575 (Div. 3) 】 RGB Substring (hard version) ( FFT)的相关文章

Codeforces Round #575 (Div. 3) D1. RGB Substring (easy version)

Codeforces Round #575 (Div. 3) D1 - RGB Substring (easy version) The only difference between easy and hard versions is the size of the input. You are given a string s consisting of n characters, each character is 'R', 'G' or 'B'. You are also given a

Codeforces Round #575 (Div. 3) D2. RGB Substring (hard version)

传送门 题意: 给你一个长为n的仅由'R','G','B'构成的字符串s,你需要在其中找出来一个子串.使得这个子串在“RGBRGBRGBRGB........(以RGB为循环节,我们称这个串为str)”里面也是一个子串,这个子串的长度是k 可是有可能s字符串中找不到,那么这个时候就可以改变s字符串中某些位置的字母来完成任务.问最少需要改变多少个字母 题解: 主要看暴力的姿势对不对.在上一道的D1上面,我是对s字符串的每一个位置进行‘R’,‘G’,‘B’的枚举,因为如果这个子串也是str的子串的话

【Codeforces Round#279 Div.2】B. Queue

这题看别人的.就是那么诚实.http://www.cnblogs.com/zhyfzy/p/4117481.html B. Queue During the lunch break all n Berland State University students lined up in the food court. However, it turned out that the food court, too, has a lunch break and it temporarily stopp

【Codeforces Round #404 (Div. 2)】题解

A. Anton and Polyhedrons 直接统计+答案就可以了. #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 1000 #define LL long long using namespace std; char s[10000]; int main() { int n; LL sum=0; scanf("%d&qu

【Codeforces Round #518 (Div. 2)】

A:https://www.cnblogs.com/myx12345/p/9847588.html B:https://www.cnblogs.com/myx12345/p/9847590.html C: D: E: F: 原文地址:https://www.cnblogs.com/myx12345/p/9847591.html

Codeforces Round #575 (Div. 3)记录

Codeforces Round #575 (Div. 3)记录 错过了上分的机会,上次不小心打了个div. 2结果直接掉了100多分. 我绿了,也变弱了.找下场Div. 3上上分吧. A 随便写了. 我的思路是三个东西先排序,一个人先拿最少的,另一个人拿次少的. 然后看剩下的能不能填补相差,如果能的话继续左右两边各补,补到剩1或0为止. 其实上面说这么多,答案就等于\(\lfloor \frac{a+b+c}{2} \rfloor\). 我是sb B 这些数与大小无关,我们直接统计有多少个奇数

Codeforces Round #501 (Div. 3) F. Bracket Substring

题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60949 ....看不懂 设dp[i][j][l]表示前i位,左括号-右括号=j,匹配到l了 状态转移,枚举下一个要填的括号,用next数组求状态的l,分别转移 代码 #include<bits/stdc++.h> using namespace std; const int maxn = 207;

【Codeforces Round #446 (Div. 2) A】Greed

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 贪心选容量大的瓶子就好 [代码] #include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5; int n; int a[N+10],b[N+10]; main(){ #ifdef LOCAL_DEFINE freopen("F:\\c++source\\rush_in.txt", "r

【Codeforces Round #446 (Div. 2) C】Pride

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 想一下,感觉最后的结果肯定是从某一段开始,这一段的gcd为1,然后向左和向右扩散的. 则枚举那一段在哪个地方. 我们设这一段中所有的数字都做了一次gcd. 假设在i..j这一段. 则求gcd的顺序是(i,i+1),(i+1,i+2)...(j-1,j) 这样a[j]=gcd(a[i],a[i+1]..a[j])了 即顺序求了一遍gcd. 这样,预处理一下i到j的gcd. 如果gcd[i][j]==1,则获取到一个可行方案. 求一