用所有合法序列的方案数减不包含题目中要求的子序列的合法序列数
后者用AC自动机维护一下dp就好
1 #include2 #include 3 #include 4 #include 5 #define mod 1000000007 6 using namespace std; 7 int n,m,cnt,tot,minu,ans; 8 char son[205]; 9 int al[205][105];10 int dp[205][205][105];11 int ed[205];12 int tr[205][2];13 int fail[205];14 void build(char b[]){15 int now=0;16 int len=strlen(b+1);17 for(int i=1;i<=len;i++){18 int k=-1;19 if(b[i]=='(')k=1;20 else k=0;21 if(!tr[now][k])tr[now][k]=++cnt;22 now=tr[now][k];23 }24 ed[now]=1;25 }26 void getfail(){27 queue que;28 int now=0;29 if(tr[0][0])que.push(tr[0][0]);30 if(tr[0][1])que.push(tr[0][1]);31 while(!que.empty()){32 int s=que.front();33 que.pop();34 if(tr[s][0]){35 fail[tr[s][0]]=tr[fail[s]][0];36 que.push(tr[s][0]);37 }else{38 tr[s][0]=tr[fail[s]][0];39 }40 if(tr[s][1]){41 fail[tr[s][1]]=tr[fail[s]][1];42 que.push(tr[s][1]);43 }else{44 tr[s][1]=tr[fail[s]][1];45 }46 }47 }48 int main(){49 scanf("%d",&n);50 scanf("%s",son+1);51 build(son);52 getfail();53 al[1][1]=1;54 for(int i=2;i<=2*n;i++){55 for(int j=0;j<=n;j++){56 (al[i][j]+=al[i-1][j+1])%=mod;57 if(j)(al[i][j]+=al[i-1][j-1])%=mod;58 }59 }60 tot=al[2*n][0];61 dp[0][0][0]=1;62 for(int i=1;i<=2*n;i++){63 for(int j=0;j<=cnt;j++){64 for(int k=0;k<=n;k++){65 if(!ed[tr[j][0]]){66 (dp[i][tr[j][0]][k]+=dp[i-1][j][k+1])%=mod;67 }68 if(!ed[tr[j][1]]&&k){69 (dp[i][tr[j][1]][k]+=dp[i-1][j][k-1])%=mod;70 }71 }72 }73 }74 for(int i=0;i