"蔚来杯"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:
- Its length is 0.
- It can be represented as (A), where A is a valid bracket sequences.
- It can be represented as AB, where A and B are both valid bracket sequence.
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的个数
一个合法的括号序列应满足以下条件:
- 序列长度为0
- 若A是合法序列,则(A)也是合法序列
- 若A和B是合法序列,则AB是合法序列
设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