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.
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.
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.
4 1 (
4
4 4 (())
1
4 3 (((
0
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.
题目大意:
给你一个长为M的括号串(只有左括号和右括号),需要在当前串的前边加一个p串,在当前串后边加一个q串,使得整个串长度为N,并且是一个匹配的串,问一共有多少种方案。
思路:
1、因为给出的字符串有一个左括号数量和右括号数量的比较问题,那么我们考虑dp其括号数量:
①设定dp【i】【j】表示长度为i的串,其中左括号比右括号多j个的方案数。
②那么不难想到其状态转移方程:
dp【i】【j】=dp【i-1】【j-1】+dp【i-1】【j+1】;
2、预处理dp数组之后,我们再考虑统计问题:
①首先我们处理一下给出的串S中,至少需要p串中含有左括号的个数,记做minn;
②然后我们设定一个变量:sumzuo,在扫s串的过程中,其遇到左括号,sumzuo++,否则sumzuo--,扫完串s之后,保留sumzuo的值,表示左括号比右括号多的个数(可能为负)。
3、
①然后我们考虑枚举p串的起点记做i,以及p串中左括号比右括号多的个数记做j。然后将p串和s串合并得到一个新的串,其中这个新的串的左括号比右括号多的个数为:j+sumzuo,而且此时我们能够得知,q串的长度为n-m-i;
②然后我们再考虑这样一点,我们想要得到的串是左右括号个数平衡的一个状态,那么考虑到dp【i】【j】还可以表示长度为i的串,其中右括号比左括号多j个的方案数。那么我们想要使得这个串是平衡的,那么我们只要保证q串中右括号比左括号多j+sumzuo个即可。
③那么我们枚举出的i,j,能够增加的方案数为:dp【i】【j】*dp【n-m-i】【j+sumzuo】;
④根据之前处理,保证i,j,n-m-i,j+sumzuo均合法即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define ll __int64
char a[100400];
ll dp[2010][2010];
ll mod=1e9+7;
int n,m;
void init()
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=2005;i++)
{
for(int j=0;j<=i;j++)
{
if(j==0)dp[i][j]=dp[i-1][j+1];
dp[i][j]=(dp[i-1][j-1]+dp[i-1][j+1])%mod;
}
}
}
int main()
{
init();
while(~scanf("%d%d",&n,&m))
{
scanf("%s",a);
int sumzuo=0,minn=0;
for(int i=0;i<m;i++)
{
if(a[i]=='(')sumzuo++;
else sumzuo--;
minn=min(minn,sumzuo);
}
ll ans=0;
for(int i=0;i<n-m+1;i++)
{
for(int j=0;j<=i;j++)
{
if(j+minn>=0&&j+sumzuo<=n-m-i)
ans+=(dp[i][j]*dp[n-m-i][j+sumzuo]);
ans%=mod;
}
}
printf("%I64d\n",ans);
}
}