Codeforces Problemset problem 629 C Famil Door and Brackets —— dp构造完美括号匹配

As Famil Door’s birthday is coming, some of his friends (like Gabi) decided to buy a present for him. His friends are going to buy a string consisted of round brackets since Famil Door loves string of brackets of length n more than any other strings!

The sequence of round brackets is called valid if and only if:

the total number of opening brackets is equal to the total number of closing brackets;
for any prefix of the sequence, the number of opening brackets is greater or equal than the number of closing brackets.
Gabi bought a string s of length m (m ≤ n) and want to complete it to obtain a valid sequence of brackets of length n. He is going to pick some strings p and q consisting of round brackets and merge them in a string p + s + q, that is add the string p at the beginning of the string s and string q at the end of the string s.

Now he wonders, how many pairs of strings p and q exists, such that the string p + s + q is a valid sequence of round brackets. As this number may be pretty large, he wants to calculate it modulo 109 + 7.

Input
First line contains n and m (1 ≤ m ≤ n ≤ 100 000, n - m ≤ 2000) — the desired length of the string and the length of the string bought by Gabi, respectively.

The second line contains string s of length m consisting of characters ‘(’ and ‘)’ only.

Output
Print the number of pairs of string p and q such that p + s + q is a valid sequence of round brackets modulo 109 + 7.

Examples
inputCopy
4 1
(
outputCopy
4
inputCopy
4 4
(())
outputCopy
1
inputCopy
4 3
(((
outputCopy
0
Note
In the first sample there are four different valid pairs:

p = “(”, q = “))”
p = “()”, q = “)”
p = “”, q = “())”
p = “”, q = “)()”
In the second sample the only way to obtain a desired string is choose empty p and q.

In the third sample there is no way to get a valid sequence of brackets.

题意:

给你这个字符串的长度和当前你知道的字符串,让你在这个字符串加一个前缀和后缀使得这个字符串是能过让括号匹配,前缀后缀可以为空

题解:

题目没看清。。以为( ( ))和( ())是一样的,注意是不一样的,这道题的范围其实也只有2000,那么就暴力dp[i][j]表示位置为i的时候有j个左括号多余,因为我们是从前面的状态转移过来的,所以不用担心右括号比左括号多或者在前面的情况,之后我们枚举前缀的长度。

#include<bits/stdc++.h>
using namespace std;
const int N=2e3+5;
#define ll long long
const ll mod=1e9+7;
ll dp[N][N];
char s[1000005];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    scanf("%s",s);
    int mx=0,sum=0;
    for(int i=0;i<m;i++)
    {
        if(s[i]=='(')
            sum++;
        else
            sum--;
        mx=max(mx,-sum);
    }
    dp[0][0]=1;
    for(int i=1;i<=n-m;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(j>0)
                dp[i][j]=dp[i-1][j-1];
            dp[i][j]=(dp[i][j]+dp[i-1][j+1])%mod;
        }
    }
    ll ans=0;
    for(int i=0;i<=n-m;i++)
    {
        for(int j=mx;j+sum<=n-m-i&&j<=i;j++)
        {
            (ans+=dp[i][j]*(dp[n-m-i][j+sum]))%=mod;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/88692859