1. 程式人生 > >Codeforces-676-C(尺取法)

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'))); }