三十年河东,三十年河西|

自动机

园龄:1年10个月粉丝:2关注:4

Atcoder Beginner Contest 312

D

题意:

给你一串由( ) ?三种字符构成的字符串,? 可以变化成( 或者 ) 问你有多少种方案把序列变成一个合法序列?

思路:

一个合法的括号序列,在每个位置上它的左括号一定要大于等于右括号的数量并且最后两个括号的数量应该相等,所以定义f[i][j]为枚举到第i个位置时左括号减右括号的差值
s[i] == '(时,当前方案数应该等于前i - 1个字符中减去一个(,反过来也一样。当s[i] == '?时此时既可以为左括号也可以为右括号,所以方案数为两者之和。

#include <bits/stdc++.h>

using namespace std;
#define more ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N = 2e5 + 5, MOD = 998244353, inf = 0x3f3f3f3f;
const long long INF = 1e18;
typedef long long LL;
typedef unsigned long long usLL;
typedef pair<int, int> PII;

int f[3010][3010]; // 前i个中,左括号 - 右括号的差为j的方案数
void solve()
{
    string s; cin >> s;
    
    f[0][0] = 1;
    for (int i = 1; i <= s.size(); i++)
    {
        for (int j = 0; j <= i; j++)
        {
            if (s[i - 1] == '(') f[i][j] = f[i - 1][j - 1] % MOD;
            if (s[i - 1] == ')') f[i][j] = f[i - 1][j + 1] % MOD;
            if (s[i - 1] == '?') f[i][j] = (f[i - 1][j - 1] + f[i - 1][j + 1]) % MOD;
        }
    }    

    cout << f[s.size()][0] << endl;
}

int main()
{
    more;
    // int T;
    // cin >> T;
    // while (T--)
    // {
    //     solve();
    // }
    solve();
    return 0;
}

本文作者:自动机

本文链接:https://www.cnblogs.com/monituihuo/articles/17591917.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   自动机  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起