加载中...

括号匹配

dp(i,j)前i个最多匹配a的前j个

给一个括号串a是b的子序列(子序列 :中间可能缺 只保留相对顺序 不考虑绝对顺序) 求子串b的合法数量

dp(i,j,k) 母串b的前i个最多匹配子串a的前j个,剩下k个左括号未匹配 z只需维护左边有几个没有被匹配的左括号就可以

a: j j+1
b: i i+1
走到b的第i位 匹配到a的第j个 子串剩下k个左括号没有匹配到右括号
如果i是左括号
而j是左括号 dp[i][j][k] -> dp[i+1][j+1][k+1] 多了一个左括号 因为ab相同匹配到j+1
而j是右括号 dp[i][j][k] -> dp[i+1][j][k+1] 多了一个左括号 因为ab不同匹配到j不变
如果i是右括号
而j是左括号 dp[i][j][k] -> dp[i+1][j][k-1]
而j是右括号 dp[i][j][k] -> dp[i+1][j+1][k-1]

#include<bits/stdc++.h>
#define ll long long
#define fors(i,a,b) for(int i = a; i < b; ++i)
#define mid ((r+l)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1,mid+1,r
#define pb push_back
#define lowbit(x) (x&(-x))
#define all(x) x.begin(),x.end()
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 205;
int dp[maxn][maxn][maxn];//走到b的第i位 匹配到a的第j个 剩下k个左括号没有匹配到子串
int n, m;
char s[maxn];
void slove() {
    cin >> n >> m;
    cin >> s; s = "?" + s + "?";
    for (int i = 0; i <= m; i++)for (int j = 0; j <= n; j++)for (int k = 0; k <= m; k++)dp[i][j][k] = 0;
    dp[0][0][0] = 1;
    for (int i = 1; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            for (int k = 0; k <= m; k++) {
                // b 的 第i位 放 (  j是已经匹配到a的第j个位置 如果下一个符号与当前考虑到的相符合 那么匹配的位置+1 否则匹配的位置保持不变
                (dp[i][j + (s[j + 1] == '(')][k + 1] += dp[i - 1][j][k]) %= mod;
                // b 的 第i位 放 ) 只有k>0才可以存在这种情况
                if (k) (dp[i][j + (s[j + 1] == ')')][k - 1] += dp[i - 1][j][k]) %= mod;
            }
        }
    }
    cout << dp[m][n][0] << endl;
}
int main(){
    ios::sync_with_stdio(false);
    int T; cin>>T;
    while(T--){
        sol();
    }
    return 0;
}
posted @ 2022-08-18 19:26  liang302  阅读(25)  评论(0编辑  收藏  举报