• CF1015F Bracket Substring (KMP+DP)


    题目大意:给你一个长度为$n$的括号序列$T$,要求你构造一个长度为$2n$的括号序列$S$,保证这个括号序列在插入数字后一定是正确的,并且$T$是$S$的一个子串

    还以为是什么纯粹的数学构造题,一通乱搞无果。好吧,并没有想到$KMP$....

    题解:首先用$KMP$预处理出数组$to[i][0/1]$,表示在$i+1$位填上括号$'('$和$')'$后匹配到字符串T的位置

    定义$f[i][j][k][0/1]$表示已经添加了$i$个括号,左右括号数量之差是$j$,已经匹配到了字符串$T$的第$k$位,是否包含$T$串

    再用$DP$转移即可,实现很简单

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N 205
     6 #define maxn 250
     7 #define uint unsigned int
     8 #define ll long long
     9 #define mod 1000000007
    10 using namespace std;
    11 
    12 int n,len;
    13 char str[N];
    14 uint f[N][N][N][2];
    15 int nxt[N],to[N][2];
    16 void get_nxt()
    17 {
    18     int i=1,j=0;nxt[1]=0;
    19     while(i<=len){
    20         if(j==0||str[i]==str[j]){
    21             i++,j++;nxt[i]=j;
    22         }else{j=nxt[j];}
    23     }
    24     for(int i=0,k;i<len;i++)
    25     {
    26         k=i;
    27         if(str[i+1]=='('){
    28             to[i][0]=k+1;k=k+1;
    29             for(;str[k]!=')'&&k;k=nxt[k]);
    30             to[i][1]=k;
    31         }else{
    32             to[i][1]=k+1;k=k+1;
    33             for(;str[k]!='('&&k;k=nxt[k]);
    34             to[i][0]=k;
    35         }
    36     }
    37 }
    38 
    39 int main()
    40 {
    41     scanf("%d",&n);
    42     scanf("%s",str+1);
    43     len=strlen(str+1);
    44     get_nxt();
    45     f[0][0][0][0]=1;
    46     for(int i=0;i<2*n;i++)
    47     {
    48         for(int j=0;j<=n;j++){
    49             for(int k=0;k<len;k++)
    50             {
    51                 if(j<n)(f[i+1][j+1][to[k][0]][to[k][0]==len]+=f[i][j][k][0])%=mod; //'('
    52                 if(j>0)(f[i+1][j-1][to[k][1]][to[k][1]==len]+=f[i][j][k][0])%=mod; //')'
    53             }
    54             if(j<n)(f[i+1][j+1][len][1]+=f[i][j][len][1])%=mod;
    55             if(j>0)(f[i+1][j-1][len][1]+=f[i][j][len][1])%=mod;
    56         }
    57     }
    58     int num=0;
    59     printf("%u
    ",f[2*n][0][len][1]);
    60     return 0;
    61 }
  • 相关阅读:
    数据库导出_导入
    vc6如何调试带参数的main函数
    配置mes
    vc调试大全
    C#中out和ref之间的区别
    TSQL 控制流语句
    删除文件夹及文件夹内的文件
    数据库 存储 研究方向 关键词
    apache 监听多端口
    js 产生随机数
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9896422.html
Copyright © 2020-2023  润新知