D - Count Bracket Sequences Editorial by en_translator
1. Properties of parenthesis string
A string \(S\) consisting of (
and )
is a parenthesis string if and only if the following two conditions are satisfied.
- For all \(i\), the first \(i\) characters of \(S\) contains more occurrences of
(
than of)
- \(S\) contains the same number of
(
and)
.
This can be shown by induction on the length of \(S\).
2. Counting
Let \(dp_{i,j}\) be the number of ways to replace each occurrence of ?
with (
or )
in the first \(i\) characters, such that (
occurs more than )
in the first \(k\) characters for all \(k \leq i\), and (the number of (
s in the first \(i\) characters) \(-\) (the number of )
s in the first \(i\) characters) \( = j\). What we want is \(dp_{N,0}\).
We describe the transitions of the DP (Dynamic Programming).
If each ?
in the first \((i-1)\) characters is replaced with (
and )
, and (the number of (
s in the first \((i-1)\) characters) \(-\) (the number of )
s in the first \((i-1)\) characters) \(= j\), then (the number of (
s in the first \(i\) characters) \(-\) (the number of )
s in the first \(i\) characters) becomes \(j+1\) if \(S_i = \) (
, \(j-1\) if \(S_i = \) )
, and \(j+1\) and \(j-1\) if \(S_i = \) ?
is replaced with (
and )
, respectively.
Therefore, the transition is as follows: if \(S_i =\) (
, then add \(dp_{i,j}\) to \(dp_{i+1,j+1}\); if \(S_i =\) )
, then add it to \(dp_{i+1,j-1}\); if \(S_i =\) ?
, then add it to \(dp_{i+1,j+1}\) and \(dp_{i+1,j+1}\).
Since there are \(O(N^2)\) states in the DP, and each transition costs \(O(1)\), so the problem has been solved in a total of \(O(N^2)\) time.
Sample code
#include <iostream>
#include <string>
#include <vector>
#include <atcoder/modint>
using namespace std;
using mint = atcoder::static_modint<998244353>;
int main() {
string s;
cin >> s;
int n = s.size();
vector<vector<mint>> dp(n + 1, vector<mint>(n + 1));
dp[0][0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (s[i] != ')') dp[i + 1][j + 1] += dp[i][j];
if (j != 0 && s[i] != '(') dp[i + 1][j - 1] += dp[i][j];
}
}
cout << dp[n][0].val() << '\n';
}
posted:
last update: