problem analysis
First, we should express the legitimacy of the bracket sequence
- The initial value of the defined variable C is 0
- Traversing the sequence from left to right, it is found that the left bracket C=C+1 and the right bracket C=C-1
- Finally, if C==0 and C has never been negative, the sequence is legal
Similarly, we can define the legitimacy of the left parenthesis
- The initial value of the defined variable C is 0
- Traverse the sequence from left to right and find that the left bracket C=C+1. When the right bracket is found and C > 0, C=C-1, otherwise C does not change
- If the final C==0, the left bracket is legal
Right parenthesis legitimacy
- The initial value of the defined variable C is 0
- Traverse the sequence from right to left and find that the right bracket C=C+1. When the left bracket is found and C > 0, C=C-1, otherwise C does not change
- If the final C==0, the right bracket is legal
Define AL, AR, ANS
- AL: the number of schemes that add the least parentheses to make the left parenthesis legal
- AR: the number of schemes that add the least parentheses to make the right parenthesis legal
- ANS: the number of schemes that add the least parentheses to make the parenthesis sequence legal
Assuming that there is a right parenthesis in the sequence that cannot change the value of C (that is, no matching left parenthesis can be found), after adding a right parenthesis to make a left parenthesis match, the single right parenthesis still cannot match any left parenthesis. Of course, the right parenthesis that has been successfully matched will not lose the left parenthesis. This means that the legitimacy of the left bracket and the legitimacy of the right bracket are independent of each other. So ANS=AL*AR
computing method
For the following sequence, write the change process of C when checking the legitimacy of the left parenthesis
((( ) (( ) (((->123 )->122 ((->12234 )->12233
The value of C is actually the maximum number of right parentheses that can be inserted in the current gap
Therefore, when the right bracket is encountered, the maximum capacity of the gap is reduced by one instead of adding a new state.
The process of legalizing the left parenthesis is to insert three right parentheses into five gaps with a capacity of 12233 respectively. However, it should be noted that there are other constraints. For example, it is illegal to put all three parentheses in the first two blanks.
This constraint is:
- No more than n parentheses can be inserted in front of the gap with capacity n.
We put the length from 0 to "C state sequence" in the outer cycle and the current gap in the inner cycle. F[n,c] represents the number of schemes that put n parentheses in the first C gaps.
The initial value of F is as follows (no matter which gap is calculated, the number of schemes with 0 parentheses must be 1)
[0 1 2 3 4 5] ->How many gaps 0 1 1 1 1 1 1 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 4 0 0 0 0 0 0 5 0 0 0 0 0 0 | Insert a few parentheses
For ()
The status sequence is 122
F will become
1 1 1 1 0 1 2 3 0 0 2 5
F[n,c]=F[n,c-1]+F[n-1.c-1]+F[n-2,c-1]...
Current item = insert 0 parentheses into the current empty space + insert 1 parenthesis into the current empty space + insert 2 parentheses into the current empty space
=Put n parentheses in the first c-1 + put n-1 parentheses in the first c-1
The constraint is n < C [C]
The final result we want is F [the capacity of the last gap, the total number of gaps]
#include<bits/stdc++.h> using namespace std; #define NMAX 5000 #define VMA1 1000000007 int N,L; int RES[NMAX+1];//C state table (void state table) long long F[NMAX+1][NMAX+1]; string input ; void init(){//Check the validity and generate the gap status table L=0; for(int i=1;i<=N;++i){ if(input[i-1]=='('){ ++L; RES[L]=RES[L-1]+1; }else{ if(RES[L]>0){ RES[L]--; } } } } long long calc(){//Calculate the number of schemes that make the left parenthesis legal memset(F,0,sizeof(F)); //There is only one solution for all gaps without inserting a bracket for(int c=0;c<=L;++c){ F[0][c]=1; } //Insert one, two for(int n=1;n<=L;++n){ //First empty, second empty for(int c=1;c<=L;++c){ //Meet constraints if(n<=RES[c]){ //Currently put 0, 1 Full or n /*for(int i=n;i>=0;--i){ F[n][c]+=F[i][c-1]; F[n][c]%=VMA1;//Anti overflow required by the topic }*/ //F[n][c-1] is currently put 1 + currently put F[n][c]=F[n-1][c]+F[n][c-1]; F[n][c]%=VMA1;//Anti overflow required by the topic } } } return F[RES[L]][L]; } int main(){ cin >> input; N=input.size(); init();//Get gap status table (left) long long v_left=calc();//Calculate the number of schemes that make the left parenthesis legal //Bracket type reversal for(int i=0;i<N;++i){ input[i]=(input[i]=='('?')':'('); } //Sequence inversion reverse(input.begin(),input.end()); init();//Get gap status table (right) long long v_right=calc();//Calculate the number of schemes that make the right bracket legal cout << (v_left*v_right)%VMA1 << endl;//Output ANS return 0; }
Note: try to write clearly, if you can't understand, please refer to 2021 Blue Bridge Cup provincial tournament java group - J bracket sequence (Full Score question solution).