补题向 | Bracket Substring(KMP+DP)

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

猜你喜欢

转载自blog.csdn.net/bekote/article/details/81571004