csp2021括号序列
主要方法:用多个数组表示不同状态,同时维护两个dp数组
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 500 + 10, mod = 1e9 + 7;
int n, k, f[N][N], g[N][N];
void add(int &x, int y) {
x = (x + y) % mod;
}
int sub(int x, int y) {
return (x + mod - y) % mod;
}
signed main(){
cin >> n >> k;
string s; cin >> s;
int len = s.size() - 1;
s = '1' + s;
for (int l = n - 1; l >= 1; l--) {
if (s[l] != '(' && s[l] != '?') continue;
for (int r = l + 1; r <= n; r++) {
if (s[r] != ')' && s[r] != '?') continue;
// ()
if (l == r - 1) add(f[l][r], 1);
// (S)
for (int i = l + 1; i <= r - 1; i++) {
if(s[i] != '*' && s[i] != '?') break;
if (i == r - 1 && l + k + 1 >= r) add(f[l][r], 1);
}
// (SA)
for (int i = l + 1; i < r - 1 && i <= k + l; i++) {
if(s[i] != '*' && s[i] != '?') break;
add(f[l][r], g[i + 1][r - 1]);
}
// (AS)
for (int i = r - 1; i > l && i >= r - k; i--) {
if(s[i] != '*' && s[i] != '?') break;
add(f[l][r], g[l + 1][i - 1]);
}
// (A)
add(f[l][r], g[l + 1][r - 1]);
// f
add(g[l][r], f[l][r]);
// AB
for (int x = l + 1; x < r; x++) add(g[l][r], f[l][x] * g[x + 1][r] % mod);
// ASB
vector<int> sum(r - l + 5, 0);
for (int i = l + 1; i <= r; i++)
sum[i - l] = (sum[i - l - 1] + g[i][r]) % mod;
int rr = 0;
// cout << f[l][r] << ' ' << g[l][r] << ' ' << l << r <<endl;
for (int x = l + 1; x < r; x++) {
if (rr <= x) rr = x + 1;
if (s[rr] != '?' && s[rr] != '*')continue;
if (rr==r) continue;
while(rr + 1 < r && (s[rr + 1] == '?' || s[rr + 1] == '*') && rr + 1 - x <= k) rr++;
add(g[l][r], f[l][x] * sub(sum[rr + 1 - l], sum[x + 1 - l]) % mod);
// cout <<"?" << rr <<sum[rr + 1 - l]<<' '<< sum[x + 1 - l]<<sub(sum[rr + 1 - l], sum[x + 2 - l])<<endl;
}
}
}
// cout<<f[1][n]<<endl;
cout << g[1][n] << endl;
}