CodeForces 204D Little Elephant and Retro Strings

本文介绍CodeForces204D题目的解题思路,该题要求找出字符串中可替换字符X后的所有可能方案,使字符串两端分别出现指定长度的全B和全W区间。

CodeForces 204D Little Elephant and Retro Strings

题目描述:

输入一个由 W 、 B 和 X 组成的字符串,你可以把 X 字符替换成 W 或者 B ,问有多少种方案使得,可以找到两个不相交的长度问 K 的区间,左边的全都由 B 组成,右边的全部由 W 组成。

题解:

为了避免重复,仅考虑最左边的长度为 K 的全 B 区间和最右边的长度为 K 的全 W 区间。

这个方案数很好求,以左边的为例,假设在前缀 i 的位置刚好出现了一个满足条件的区间 [iK,i] ,那么前缀 i 仅出现一次满足要求的区间的方案数就是前缀 i1 的方案数,加上前缀 iK1 中没有满足要求的区间(这保证了区间 [iK,i] 首次出现)的方案数。

右边的用同样的方式求,最后把两个合并起来就行了。

题目链接: vjudge 原网站

代码:

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

#define MAXN 1000007

const long long MOD = 1000000007LL;

static int N, K;
static long long sum, not_b[MAXN], not_w[MAXN], dp[MAXN], num[MAXN];
static char S[MAXN];

inline long long pow(long long x, long long y)
{
    long long ans = 1;
    for (; y; y >>= 1, (x *= x) %= MOD)
        if (y & 1) (ans *= x) %= MOD;
    return ans;
}

int main()
{
    scanf("%d%d%s", &N, &K, S + 1);
    num[N + 1] = 1;
    for (int i = N; i; i--)
        num[i] = S[i] == 'X' ? 2LL * num[i+1] % MOD : num[i+1];
    not_b[0] = 1;
    for (int i = 1, last = 0; i <= N; i++)
    {
        last = S[i] == 'W' ? 0 : last + 1;
        not_b[i] = S[i] == 'X' ? 2LL * not_b[i-1] % MOD : not_b[i-1];
        dp[i] = dp[i-1];
        if (K <= last && S[i-K] != 'B')
        {
            long long sub = i == K ? 1 : not_b[i-K-1];
            (not_b[i] += MOD - sub) %= MOD;
            (dp[i] += sub * num[i+1]) %= MOD;
        }
    }
    not_w[N + 1] = not_w[N + 2] = 1;
    for (int i = N, last = 0; i; i--)
    {
        last = S[i] == 'B' ? 0 : last + 1;
        not_w[i] = S[i] == 'X' ? 2LL * not_w[i+1] % MOD : not_w[i+1];
        if (K <= last && S[i+K] != 'W')
        {
            long long sub = not_w[i+K+1];
            (not_w[i] += MOD - sub) %= MOD;
            (sum += sub * dp[i-1] % MOD * pow(num[i], MOD - 2) % MOD) %= MOD;
        }
    }
    printf("%lld\n", sum);
    return 0;
}

提交记录(AC / Total = 1 / 1):

Run IDRemote Run IDTime(ms)Memory(kb)ResultSubmit Time
877286326349680106034140AC2017-04-14 11:05:14
虽然给定引用中未直接提及“Kuroni and Simple Strings”题目的详细信息,但通常这类题目可能与字符串处理、括号匹配等相关。一般而言,题目可能会给出一个由括号组成的字符串,要求找出能移除的最大数量的不相交的合法括号对,并输出移除这些括号对后的相关信息。 ### 解法分析 #### 栈解法 栈解法是处理括号匹配问题的经典方法。通过遍历字符串,将左括号压入栈中,遇到右括号时,若栈顶为左括号,则将栈顶元素弹出,表示这是一对匹配的括号。 ```python s = input() stack = [] pairs = [] for i, char in enumerate(s): if char == '(': stack.append(i) else: if stack: left_index = stack.pop() pairs.append((left_index + 1, i + 1)) if not pairs: print(0) else: print(1) print(len(pairs) * 2) result = [] for l, r in pairs: result.extend([l, r]) result.sort() print(" ".join(map(str, result))) ``` #### 双指针解法 双指针解法从字符串的两端向中间遍历,分别使用两个指针 `left` 和 `right`。`left` 指针从左向右寻找 `(`,`right` 指针从右向左寻找 `)`,当找到一对匹配的括号时,将它们标记为已移除,继续寻找下一对匹配的括号,直到无法再找到匹配的括号为止。 ```python s = input() n = len(s) left = 0 right = n - 1 pairs = [] while left < right: while left < right and s[left] != '(': left += 1 while left < right and s[right] != ')': right -= 1 if left < right: pairs.append((left + 1, right + 1)) left += 1 right -= 1 if not pairs: print(0) else: print(1) print(len(pairs) * 2) result = [] for l, r in pairs: result.extend([l, r]) result.sort() print(" ".join(map(str, result))) ``` ### 复杂度分析 - **栈解法**:时间复杂度为 $O(n)$,其中 $n$ 是字符串的长度。空间复杂度为 $O(n)$,主要用于栈的空间开销。 - **双指针解法**:时间复杂度为 $O(n)$,空间复杂度为 $O(n)$,主要用于存储匹配的括号对。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值