Codeforces Round #501 (Div. 3) F. Bracket Substring
https://codeforces.com/problemset/problem/1015/F
dp
'求包含某个子串的个数' 类型
kmp
///it is advised that all character begins at index 1
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 const double eps=1e-8; 12 const ll inf=1e9; 13 const ll mod=1e9+7; 14 const int maxn=2e2+10; 15 16 char sstr[maxn]; 17 18 int str[maxn],pre[maxn],nex[maxn][2]; 19 ll f[maxn][maxn][maxn][2]; 20 21 int main() 22 { 23 int n,nn,len,i,j,k,l,m,jj,lll; 24 scanf("%d",&n); 25 nn=n<<1; 26 ///it is advised that all character begins at index 1 27 scanf("%s",sstr+1); 28 len=strlen(sstr+1); 29 for (i=1;i<=len;i++) 30 if (sstr[i]=='(') 31 str[i]=0; 32 else 33 str[i]=1; 34 35 ///kmp makes O(1) visit 36 j=0; 37 pre[1]=0; 38 for (i=2;i<=len;i++) 39 { 40 while (j!=0 && str[j+1]!=str[i]) 41 j=pre[j]; 42 if (str[j+1]==str[i]) 43 j++; 44 pre[i]=j; 45 } 46 47 for (i=0;i<=len-1;i++) 48 for (j=0;j<=1;j++) 49 if (str[i+1]==j) 50 nex[i][j]=i+1; 51 else 52 nex[i][j]=nex[pre[i]][j]; 53 54 f[0][0][0][0]=1; 55 ///pos ith 56 for (i=1;i<=nn;i++) 57 ///j '(' 58 for (j=0;j<=min(i-1,n);j++) 59 ///current char 60 for (k=0;k<=1;k++) 61 { 62 jj=j+1+(-2)*(k==1); 63 if (jj==-1) 64 continue; 65 (f[i][jj][0][1]+=f[i-1][j][0][1])%=mod; 66 ///the lth str 67 for (l=0;l<=min(len-1,i-1);l++) 68 { 69 lll=nex[l][k]; 70 if (lll==len) 71 (f[i][jj][0][1]+=f[i-1][j][l][0])%=mod; 72 else 73 (f[i][jj][lll][0]+=f[i-1][j][l][0])%=mod; 74 } 75 } 76 printf("%lld",f[nn][0][0][1]); 77 return 0; 78 }