CF 676C. Vasya and String 尺取经典题目

C. Vasya and String
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

High school student Vasya got a string of length n as a birthday present. This string consists of letters 'a' and 'b' only. Vasya denotes beauty of the string as the maximum length of a substring (consecutive subsequence) consisting of equal letters.

Vasya can change no more than k characters of the original string. What is the maximum beauty of the string he can achieve?

Input

The first line of the input contains two integers n and k (1 ≤ n ≤ 100 000, 0 ≤ k ≤ n) — the length of the string and the maximum number of characters to change.

The second line contains the string, consisting of letters 'a' and 'b' only.

Output

Print the only integer — the maximum beauty of the string Vasya can achieve by changing no more than k characters.

Examples
input
Copy
4 2
abba
output
Copy
4
input
Copy
8 1
aabaabaa
output
Copy
5
Note

In the first sample, Vasya can obtain both strings "aaaa" and "bbbb".

In the second sample, the optimal answer is obtained with the string "aaaaabaa" or with the string "aabaaaaa".

需要修改其中最多的k个使n个只包含两种字符的最长子串

一个用来枚举现在的Right(变量i),还有一个Left(变量L)用来记录从L到R改变change个字符的连续个数

0和1都需要处理一次

尺取为什么正确呢,首先看复杂度,我循环是2n,Left循环一次,Right循环一次

我每次改变的元素个数是固定的,可以拿到

不考虑复杂度我就是进行n^2的循环去枚举开始和结束,你也可以前缀和去记录下当前有几个a几个b(把一个为1,一个为0),改变a或者改变b均可

但是这个复杂度太差了,其实我们可以更改的位置是固定的,如果我们要找a串,就是b要改为a(否则相反)位置固定,假如我们要多改一个就是向后延伸,怎么去找到改变的这个位置,其实就是找到你之前第一个把b改为a的地方,利用Left去标记开始就好了,也就是还要改变k个的位置

#include <bits/stdc++.h>
using namespace std;
int n,k;
string s;
//要改为c的最大值
int cal(char c)
{
    //L为当前枚举的开始
    int L=0,change=0,ans=0;
    for(int i=0;s[i];i++)
    {
        //是需要改变的
        if(s[i]==c)
        {
            //还有机会
            if(change<k)
            {
                change++;
            }
            else
            {
                //没机会了要往后移,要移到第一个改变的位置
                while(L<i&&s[L]!=c)L++;
                //找到了+1,因为开始是下一个
                L++;
            }
        }
        //从L到i共有i-L+1个数
        ans=max(ans,i-L+1);
    }
    return ans;
}
int main()
{
    cin>>n>>k>>s;
    cout<<max(cal('a'),cal('b'));
    return 0;
}

 二分+前缀和,前缀和可以看出要改几个,就是我上面提出的一个优化,若ans+1满足,ans肯定也满足,满足单调性

#include <bits/stdc++.h>
using namespace std;
int n, k;
string s;
int sum[100005];
int check(int x)
{
    for (int i = 0; i + x <= n; i++)
    {
        if (sum[i + x] - sum[i] >= x - k || sum[i + x] - sum[i] <= k)
            return 1;
    }
    return 0;
}

int main()
{
    cin >> n >> k >> s;
    sum[0] = 0;
    for (int i = 0; s[i]; i++)
    {
        if (s[i] == 'b')
            sum[i + 1] = sum[i] + 1;
        else
            sum[i + 1] = sum[i];
    }
    //二分答案
    int L = 1, R = n, ans;
    while (L <= R)
    {
        int mid = (L + R) / 2;
        //检查成功,mid可以是答案,继续搜索
        if (check(mid))
            ans = mid, L = mid + 1;
        else
            R = mid - 1;
    }
    cout << ans << "\n";
    return 0;
}

 

posted @ 2020-02-04 17:40  暴力都不会的蒟蒻  阅读(337)  评论(0编辑  收藏  举报