Codeforces-676-C(尺取法)

Codeforces 676C - Vasya and String

题目原址

[http://codeforces.com/contest/676/problem/C]

题意

给一个 n 个字符(只含 ab )的字符串,通过改变当中的 k 个字符( a 改为 bb 改为 a ),求改变后字符串的连续子序列(只含 a ,或者只含 b )的最大长度。

题解

尺取法

两个可移动的端点 去量所给定的数组(字符串是char数组),通过给定的条件来 更变两个端点的位置来搜寻最值。
在这道题中,我们可以分两种情况来搜寻最长连续子序列的长度,这个子序列 1. 只含a, 2. 只含b。
对于任意其中一种情况,操作相同,下面以找最长 a 连续子序列长度为例:

  1. 初始化左右端点为0,答案为0,计数器(记录更改字符的数量)为0
  2. 判断右端点是否小于 n ,是进入第3步,否则进入第9步
  3. 判断该字符是不是 a ,是进入第4步,否则进入第5步
  4. 该字符是 a ,继续扩长,右端点+1,去第8步
  5. 判断是否还能改变该 ba,(计数器是否小于 k ),能进入第6步,否则第7步
  6. 能改继续改,计数器+1,右端点+1,去第8步
  7. 不能改了就将最左端的 b 去掉,使得现在这个 b 能够更改。即:循环如果左端点的值是 a ,则左端点+1,否则退出循环,且左端点+1,右端点+1,然后去第8步
  8. 取新的答案为原来答案和现在答案(右-左+1)的最大值,然后回到第2步。
  9. 现在答案就是最长 a 的连续子序列的长度

实现

#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int n, k;
char s[maxn];

int solve(char c) {
    int l = 0;
    int r = 0;
    int cnt = 0;
    int ans = 0;

    while (r < n) {//观察上面步骤发现无论如何右端点总是要+1,故把所有r++合成1个
        if (s[r] != c)//不是所要字符的话
            if (cnt >= k)//如果不能更改了的话
                while (s[l++] == c)//左端点仍然是c时
                    continue;
            else
                cnt++;
        r++;
        ans = max(ans, r - l);
    }
    return ans;
}
int main() {
    scanf("%d%d%s", &n, &k, s);
    printf("%d\n", max(solve('a'), solve('b')));
}

猜你喜欢

转载自blog.csdn.net/weixin_43406046/article/details/84065197
今日推荐