Vasya and String(尺取法)

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
4 2
abba
Output
4
Input
8 1
aabaabaa
Output
5
题目分析:
尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。之所以需要掌握这个技巧,是因为尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的时候,所以尺取法是一种高效的枚举区间的方法,一般用于求取有一定限制的区间个数或最短的区间等等。当然任何技巧都存在其不足的地方,有些情况下尺取法不可行,无法得出正确答案。
这一段话取自以下文章。

原文链接:https://blog.csdn.net/consciousman/article/details/52348439

而对于这个题,就是从头开始扫描,根据贪心的原则,每次只有只改a或b字符时序列长度才有可能最大,所以我们分两次循环进行。分别是去除a字符和b字符
具体的实现过程是:

int t1=k,t2=k;//把k存储一下
    int left=0,right=0;//从左向右移动的指针
while(left<right&&right<n)//先去掉a字符
    {
        if(s[right]=='a') t1--;
        if(t1<0)//当遇到k+1次a时
        {
            while(s[left]=='b') left++;//当遇到a时停止
            left++;//使当前left到right序列内没有多余a
            t1=0;
        }
        maxl=max(maxl,right-left+1);//取最优值
        right++;
    }

从左向右移动right指针,把k当作可以修改的上限次数,拿去掉a字符为例,每遇到一次a字符,就k–,当k==0时,说明所有次数都用完了,这时如果再遇到a字符,那么k就变成了-1,此时小于零,那么为了维护你的使用次数上限,就必须要找到你遇到的第一个a字符,将它去掉,再把k赋值为0,相当于更新了一次序列,那好,我们就可以按照这个思路来进行,实用性还是相当高的。第一次用的时候不太会,拿纸来模拟了一遍小数据,这时候脑子里就有了一个框架了,再遇到类似的题也很容易想到。
完整代码:

#include<iostream>
using namespace std;
const int max_n=1e5+10;
char s[max_n];
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++)
        cin>>s[i];
    int t1=k,t2=k;//把k存储一下
    int left=0,right=0;//从左向右移动的指针
    int maxl=-1;
    while(left<right&&right<n)//先去掉a字符
    {
        if(s[right]=='a') t1--;
        if(t1<0)//当遇到k+1次a时
        {
            while(s[left]=='b') left++;//当遇到a时停止
            left++;//使当前left到right序列内没有多余a
            t1=0;
        }
        maxl=max(maxl,right-left+1);//取最优值
        right++;
    }
    left=0;right=0;
    while(left<=right&&right<n)//这次该去除b啦
    {
        if(s[right]=='b') t2--;
        if(t2<0)
        {
            while(s[left]=='a') left++;
            left++;
            t2=0;
        }
        maxl=max(maxl,right-left+1);
        right++;
    }
    cout<<maxl;
    return 0;
}
发布了42 篇原创文章 · 获赞 42 · 访问量 9311

猜你喜欢

转载自blog.csdn.net/amazingee/article/details/104534150