Codeforces-676-C(尺取法)
阿新 • • 發佈:2018-11-15
Codeforces 676C - Vasya and String
題目原址
[http://codeforces.com/contest/676/problem/C]
題意
給一個 n 個字元(只含 a 或 b )的字串,通過改變當中的 k 個字元( a 改為 b , b 改為 a ),求改變後字串的連續子序列(只含 a ,或者只含 b )的最大長度。
題解
尺取法
用 兩個可移動的端點 去量所給定的陣列(字串是char陣列),通過給定的條件來 更變兩個端點的位置來搜尋最值。
在這道題中,我們可以分兩種情況來搜尋最長連續子序列的長度,這個子序列 1. 只含a, 2.
對於任意其中一種情況,操作相同,下面以找最長 a 連續子序列長度為例:
- 初始化左右端點為0,答案為0,計數器(記錄更改字元的數量)為0
- 判斷右端點是否小於 n ,是進入第3步,否則進入第9步
- 判斷該字元是不是 a ,是進入第4步,否則進入第5步
- 該字元是 a ,繼續擴長,右端點+1,去第8步
- 判斷是否還能改變該 b 為 a,(計數器是否小於 k ),能進入第6步,否則第7步
- 能改繼續改,計數器+1,右端點+1,去第8步
- 不能改了就將最左端的 b 去掉,使得現在這個 b 能夠更改。即:迴圈如果左端點的值是 a ,則左端點+1,否則退出迴圈,且左端點+1,右端點+1,然後去第8步
- 取新的答案為原來答案和現在答案(右-左+1)的最大值,然後回到第2步。
- 現在答案就是最長 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')));
}