【题意】

定义一个合法串:

(1),'('的总数 == ')'的总数。

(2), 串中所有前缀 满足 '('的个数 >= ')'的个数。

题意:给定一个合法串的长度n和一个长度为m的中间串s,要求你找到一个p串和q串,使得p + s + q是一个合法串且长度为n。问有多少种不同的方案数。 结果 % (1e9+7)。

【解题方法】

设置dp[i][j]表示长度为i的合法串且'('的个数 - ')'的个数 == j的方案数。

我们称j为该串的平衡度。其实dp[i][j] = dp[i][-j],因为'('和')'可以互换。

转移有dp[i][j] = dp[i-1][j+1] + dp[i-1][j-1]。

那么我们可以枚举p串的长度和平衡度,找到合法的q串。再统计方案数。

注意:我们不能仅仅要求p + s + q合法就够了,必须保证选出的p + s也是一个合法串。

假设p + s长度为i且平衡度为j(j>=0)。那么q串长度为n-m-i,平衡度为-j。

【AC code】
#include <bits/stdc++.h>
using namespace std;
const int maxn=2005;
const int mod=1e9+7;
long long dp[maxn][maxn];
const int inf=0x3f3f3f3f;
int n,m;
string str;
void add(long long &x,long long y){
    x+=y;
    x%=mod;
}
void init(){
    memset(dp,0,sizeof(dp));
    dp[0][0]=1LL;
    for(int i=1; i<=2000; i++){
        dp[i][0]=dp[i-1][1];
        for(int j=1; j<=i; j++){
            add(dp[i][j],(dp[i-1][j+1]+dp[i-1][j-1])%mod);
        }
    }
}

int main()
{
    init();
    cin>>n>>m;
    cin>>str;
    int minn=inf;
    int sum=0;
    for(int i=0; i<m; i++){
        if(str[i]=='(') sum++;
        else sum--;
        minn=min(minn,sum);
    }
    int len=n-m;
    long long ans=0;
    for(int i=0; i<=len; i++){
        for(int j=0; j<=i; j++){
            if(j+minn<0||len-i<j+sum) continue;
            add(ans,dp[i][j]*dp[len-i][j+sum]);
        }
    }
    cout<<ans<<endl;
}