代码源:999、最长的X

140 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情 logo.png

题目描述

这是代码源5月31日的div2每日一题

最长的 X - 题目 - Daimayuan Online Judge

给定一个由 X 和 . 组成的字符串 S。

你能对字符串 S 做以下操作 0 到 K 次(包括 0 和 K):

将一个 . 替换为 X

请问操作完的字符串 S 中最多可能有多少个连续的 X?

输入格式

第一行一个字符串 S

第二行一个整数 K

输出格式

一个整数,表示答案

样例输入

XX...X.X.X.
2

样例输出

5

数据范围

​ 对于全部数据保证 1≤|S|≤2×105,0≤K≤2×105。

问题解析

双指针写法,为了方便我们这里先预处理一个前缀和数组,我们把字符串的'.'看成1,'X'看成0来计算前缀和。

然后快慢指针遍历前缀和数组,如果快指针r到慢指针l这一段的区间和:

小于等于k,说明这一段的‘.'我们都可以把他们变成’X',那么这一段都可以是‘X',快指针走一步。

如果大于k了,说明这一段的’.'我们并不能全变成‘k',即这一段并不是连续的'X',那么我们慢指针走一步,如果两个指针是在同一个位置,那么快指针也要走一步。

每次计算完一个区间值后,我们更新一下最大区间长度,最后把维护的值输出即可。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include <sstream>

#define endl '\n'
#define int ll
typedef long long ll;
typedef pair<ll, ll>PII;
typedef unsigned long long ull;

string s;
int k, n;
int sum[200005];

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin >> s >> k;
    int n=s.size();
    if (k > n)
    {
        cout << n << endl;
        return 0;
    }
    for (int i = 1; i <= n; i++)
    {
        if (s[i - 1] == 'X')sum[i] = sum[i - 1];
        else sum[i] = sum[i - 1] + 1;
    }
    int res = 0, l = 1, r = 1;
    while (r <= n)
    {
        if (sum[r] - sum[l - 1] <= k)
        {
            r++;
            res = max(r - l, res);
        }
        else
        {
            if (l == r)r++;
            l++;
        }
        
    }
    cout << res;
    return 0;
}