F. Bracket Substring
求能够构造的符合要求的,包含s序列,长度为2n的序列数量
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<bitset>
#include<utility>
using namespace std;
typedef long long ll;
const double eps=0.0000000000001;
const int mod=1000000007;
int n;
char s[210];
ll dp[210][210][210];//长度为i,和S匹配的长度为j,还剩k个左括号未匹配的序列的构造方案数
int nt[210];
void getN(int m){
int k=-1;
int i=0;
nt[0]=-1;
while(i<m){
if(k==-1||s[i]==s[k]){
i++;k++;
nt[i]=k;
}
else{
k=nt[k];
}
}
}
void debug(int m){
for(int i=0;i<m;i++){
cout<<nt[i]<<" ";
}
cout<<endl;
}
void debug1(int m){
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
for(int k=0;k<=n;k++){
cout<<dp[i][j][k]<<" ";
}
cout<<endl;
}
cout<<"******************"<<endl;
}
}
int main(){
while(~scanf("%d",&n)){
n*=2;
scanf("%s",&s);
int m=strlen(s);
if(m>n){
printf("0\n");
continue;
}
getN(m);//KMP next数组加速匹配
//debug(m);
memset(dp,0,sizeof(dp));
if(s[0]=='('){
dp[1][1][1]=1;
}
else dp[1][0][1]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<=m&&j<=i;j++){
for(int k=0;k<=i;k++){
if(j==m){
dp[i][j][k+1]+=dp[i-1][j][k];
dp[i][j][k+1]%=mod;
if(k!=0){
dp[i][j][k-1]+=dp[i-1][j][k];
dp[i][j][k-1]%=mod;
}
continue;
}
if(s[j]=='('){
dp[i][j+1][k+1]+=dp[i-1][j][k];
dp[i][j+1][k+1]%=mod;
//第i个元素为左括号
if(k!=0){
int t=nt[j];
while(s[t]=='('&&t!=-1){
t=nt[t];
}
dp[i][t+1][k-1]+=dp[i-1][j][k];
dp[i][t+1][k-1]%=mod;
}
//右括号
}
else{
if(k!=0){
dp[i][j+1][k-1]+=dp[i-1][j][k];
dp[i][j+1][k-1]%=mod;
}
int t=nt[j];
while(s[t]==')'&&t!=-1){
t=nt[t];
}
dp[i][t+1][k+1]+=dp[i-1][j][k];
dp[i][t+1][k+1]%=mod;
}
}
}
}
//debug1(m);
printf("%I64d\n",dp[n][m][0]);
}
return 0;
}
只想说,不看题解,完全想不到DP怎么建,这种完全看不到前方的感觉,最低!o(╥﹏╥)o