其他分享
首页 > 其他分享> > "蔚来杯"2022牛客暑期多校训练营2 K-Link with Bracket Sequence I

"蔚来杯"2022牛客暑期多校训练营2 K-Link with Bracket Sequence I

作者:互联网

问题描述

Link has a bracket sequence a of length n, which is a subsequence of a valid bracket sequence b of length m.

Link doesn't remember b, so he wonders the number of possible sequences b.

A bracket sequence is valid if it satisfies any of the following conditions:

A sequence a is a subsequence of a sequence b if a can be obtained from b by deletion of several (possibly, zero or all) elements.

输入格式

Each test contains multiple test cases. The first line contains the number of test cases T (1≤T≤100). Description of the test cases follows.

The first line contains two integers n,m (1≤n≤m≤200).

The second line contains a bracket sequence s of length n.

It is guaranteed that the sum of m over all test cases does not exceed 103.

输出格式

For each test cases, output the number of possible sequences b modulo 109+7.

Note that the answer maybe 0 due to Link's poor memory.

样例输入

3
2 2
()
2 4
)(
2 4
()

样例输出

1
1
2

题解

Link有一个长度为n的括号序列a,它是长度为m的合法括号序列m的子序列

Link不记得b,所以他想知道可能的b的个数

一个合法的括号序列应满足以下条件:

设f[i][j][k]表示b的长度为i,a的前j个是b的子序列,且左括号个数比右括号多k(即有k的单独的左括号)的方案数

为什么左括号个数不能少于右括号

因为我们构造b时是通过在字符串末尾添加字符构造的,如果左括号个数大于右括号,可以通过后期加右括号使最终序列合法,如果右括号多于左括号,要使最终序列合法需要在前面添加左括号,但是我们构造b时只能在后面添加字符,所以若右括号多于左括号就不可能构成合法序列

显然,f[0][0][0]=1

设当前已构造出长度为i的b,对于b的第i+1个字符

第一种情况:左括号

  当a[i+1]是左括号时,直接将a[i+1]接在b末尾,f[i+1][j+1][k+1]+=f[i][j][k]

  当a[i+1]是右括号时,不使用a[i+1],在b末尾额外加一个左括号f[i+1][j][k+1]+=f[i][j][k]

第二种情况:右括号

  每加一个右括号,前面必须有单独的左括号与其配对,即左括号的个数要严格大于右括号

  而由于左括号被配对掉一个,左右括号个数差变为k-1

  当a[i+1]是左括号时,不使用a[i+1],直接在b末尾加一个右括号,f[i+1][j][k-1]+=f[i][j][k]

  当a[i+1]是右括号时,将a[i+1]接在b末尾,f[i+1][j+1][k-1]+=f[i][j][k]

 

 1 #include <cstring>
 2 #include <cstdio>
 3 const int mo = 1e9+7;
 4 int T,n,m,f[205][205][205];
 5 char s[205];
 6 void add(int &x,int y)
 7 {
 8     x=(x+y)%mo;
 9     return;
10 }
11 int main()
12 {
13     int i,j,k;
14     scanf("%d",&T);
15     while (T--)
16     {
17         scanf("%d%d%s",&n,&m,s+1); 
18         memset(f,0,sizeof(f));
19         f[0][0][0]=1; 
20     for (i=0;i<m;i++) 
21       for (j=0;j<=n;j++)
22         for (k=0;k<=i;k++)
23         {
24             add(f[i+1][j+(s[j+1]=='(')][k+1],f[i][j][k]);
25             if (k) add(f[i+1][j+(s[j+1]==')')][k-1],f[i][j][k]);
26         }
27         printf("%d\n",f[m][n][0]);
28     }
29     return 0;
30 }

 

标签:sequence,int,蔚来,Sequence,多校,括号,test,Link,序列
来源: https://www.cnblogs.com/rabbit1103/p/16517939.html