codeforces 629C Famil Door and Brackets(dp)

11 篇文章 0 订阅
8 篇文章 0 订阅

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:

  1. the total number of opening brackets is equal to the total number of closing brackets;
  2. 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
input
4 1
(
output
4
input
4 4
(())
output
1
input
4 3
(((
output
0

solution:
先统计字符串s中‘(’的最小前缀和为minn,s中前缀和为x,那么p只需要满足p的前缀和+minn>=0,符合这样的不等式的p都是可行解,那么我们预处理出一个dp[i][j],代表i个括号平衡度为j的个数,那么之后枚举p的长度i和p的平衡度j,在满足 p的前缀和(j)+minn>=0q的前缀和(j+x)<=m-n-i(及q的长度) 其实在这里q的前缀和应该为-(j+x),因为总体前缀和应为0 但因为对称 所以可看成j+x

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 200;
const int mod = 1e9 + 7;
char s[maxn];
long long dp[2500][2500];
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	scanf("%s", s + 1);
	dp[0][0] = 1;
	for (int i = 1; i <= n - m; i++)//预处理长度为n-m,平衡度为0~i的dp[i][j]
		for (int j = 0; j <= i; j++)
			if (j > 0)dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1])%mod;
			else dp[i][j] = dp[i - 1][j+1];
	int minn = m+1,x=0;
	for (int i = 1; i <= m; i++)
	{
		if (s[i] == '(')x++;
		else x--;
		minn = min(minn, x);
	}
	long long ans = 0;
	for (int i = 0; i <= n - m; i++)
		for (int j = 0; j <= i; j++)
			if (j + minn >= 0 && j + x <= n - m - i)
				ans = (ans + dp[i][j] * dp[n - m - i][j + x]) % mod;
	printf("%I64d\n", ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值