• "蔚来杯"2022牛客暑期多校训练营2 KLink 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 }
  • 相关阅读:
    20210110-正则表达式
    20210105
    C# Expression 树转化为SQL语句(一)
    5000行js db
    Keras智能
    nginx 设置多个tcp IP代理 socket 转发
    FTP连接时出现“227 Entering Passive Mode” 的解决方法
    windows nginx TCP代理 负载均衡
    nginx 代理ftp
    Intellij IDEA添加项目依赖
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/16517939.html
Copyright © 2020-2023  润新知