开头感谢提交列表里的大佬们,以及题解里大佬提供的思路。 本题的思路是这样的,自底向上递推出s1和s2串的合法括号匹配数, 比如本题中有两个变量,i表示s1串下标,j表示s2串下标。 我们假设状态dp[i][j],表示是s1串i到s2串j的左括号>=0的个数。 接下来我们从案例出发: 先从dp[1][1]开始着手,dp[1][1]按例题中的案例1, 是两个符号 ( ( 以粗体表示s1串的符号 总共两种匹配方式,((和(( 再看dp[1][0] 只有**(** 这种情况 dp[0][1] 只有(这种情况 我们可以得出dp[1][1]=2 dp[1][0]=dp[0][1]=1 可以通过推测dp[1][1]=dp[1][0]+dp[0][1] 再次得到dp[2][1]=dp[1][1]+dp[2][0] 因为dp[2][0]=1 又因为dp[2][0]=dp[1][0]+dp[2][-1] i<0或者j<0 应当不存在
我们基本可以得到公式了 dp[i][j]=dp[i-1][j]+dp[i][j-1] 因为子问题可能是不合法(a[len1]+b[len2]>=0),但最终一定会合法即a[len1]+b[len2]==0 剩下要在代码中体会了。 至于dp[0][0]=1 就是由dp[1][0]和dp[0][1]得出了.

以下是代码:

#include<cstring>
using namespace std;
const int N = 1e9 + 7;
typedef long long ll;
string s1,s2;
int dp[2501][2501];
int a[2501],b[2501];
int main(){
    cin >> s1>>s2;
    int len1=s1.length(),len2=s2.length();
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    memset(dp,0,sizeof(a[0])*sizeof(int));
    for(int i =1;i<=len1;i++){//可以理解为求左括号个数 个数为正  左括号>右括号  =0  左括号=右括号 为负    左括号<右括号
        if(s1[i-1]=='(')a[i]=a[i-1]+1;
        else a[i]=a[i-1]-1;
    }
    for(int j =1;j<=len2;j++){//可以理解为求左括号个数 个数为正  左括号>右括号  =0  左括号=右括号 为负    左括号<右括号
        if(s2[j-1]=='(')b[j]=b[j-1]+1;
        else b[j]=b[j-1]-1;
    }
    if(a[len1]+b[len2]!=0){//比较左右括号 左括号 != 右括号 不配对 
        cout <<0<<endl;
        return 0;
    }
    dp[0][0]=1;
    for(int i = 0;i<=len1;i++)
        for(int j =0;j<=len2;j++){
            if(a[i]+b[j]>=0){
                if(i)
                    dp[i][j]+=dp[i-1][j];
                if(j)
                    dp[i][j]+=dp[i][j-1];
                dp[i][j]%=N;
            }
        }
    cout << dp[len1][len2];
    return 0;
}

在提交时,发现内存爆了 在初始化是 6,7行初始化过大空间

ll dp[2501][2501];
int a[2510],b[2510];

改成上面那般就过了,很神奇。