括号匹配,结果为匹配后的串
一、记忆化搜索(search with finger):
从[0, strlen(s)-1] 开始搜索,缩短区间,期间记录搜索过的值,防止重复
cut[l][r]代表区间[l, r]中需要从哪里分割,为输出
串长不超过100 复杂度可以接受
1 // Brackets sequence 2 // Search with fingers 3 4 #include <iostream> 5 #include <string> 6 #include <algorithm> 7 #include <cstring> 8 #include <cstdio> 9 10 #define MAXN 100 11 12 int n, dp[MAXN+10][MAXN+10], cut[MAXN+10][MAXN+10]; 13 char s[111]; 14 15 int SearchWithFinger(int l, int r) 16 { 17 if(l > r) 18 return dp[l][r] = 0; 19 if(l == r) 20 return dp[l][r] = 1; 21 if(dp[l][r]!=-1) 22 return dp[l][r]; 23 24 int num = 1<<30; 25 if( (s[l]=='('&&s[r]==')')||(s[l]=='['&&s[r]==']') ) 26 num = std::min(num, SearchWithFinger(l+1, r-1)); 27 else if(s[l]=='('||s[l]=='[') 28 num = std::min(num, SearchWithFinger(l+1, r)+1); 29 else if(s[r]==')'||s[r]==']') 30 num = std::min(num, SearchWithFinger(l, r-1)+1); 31 32 for(int m = l; m < r; ++m){ 33 int temp = SearchWithFinger(l, m) + SearchWithFinger(m+1, r); 34 if(num >= temp){ 35 num = temp; 36 cut[l][r] = m; 37 } 38 } 39 40 return dp[l][r] = num; 41 42 } 43 44 void PrintOut(int l, int r) 45 { 46 if(l > r) 47 return; 48 if(l == r){ 49 if(s[l]=='('||s[l]==')') 50 printf("()"); 51 if(s[l]=='['||s[l]==']') 52 printf("[]"); 53 } 54 else{ 55 if(cut[l][r] >= 0){ 56 PrintOut(l, cut[l][r]); 57 PrintOut(cut[l][r]+1, r); 58 } 59 else{ 60 if(s[l]=='(' ){ 61 printf("("); 62 PrintOut(l+1, r-1); 63 printf(")"); 64 } 65 if(s[l]=='['){ 66 printf("["); 67 PrintOut(l+1, r-1); 68 printf("]"); 69 } 70 } 71 } 72 73 } 74 75 int main(int argc, char const *argv[]) 76 { 77 // freopen("in", "r", stdin); 78 // freopen("out", "w", stdout); 79 scanf("%d", &n); 80 getchar(); 81 while(n--){ 82 83 getchar(); 84 gets(s); 85 86 87 memset(dp, -1, sizeof(dp)); 88 memset(cut, -1, sizeof(cut)); 89 90 SearchWithFinger(0, strlen(s)-1); 91 92 PrintOut(0, strlen(s)-1); 93 94 printf("\n"); 95 if(n) 96 printf("\n"); 97 } 98 return 0; 99 }
二、区间DP
dp[l][r]代表从区间[l, r]的串需要添加至少多少个括号才能匹配
枚举区间长度len : 1 to strlen(s)-1
dp[i][i] = 0 任何一个单独的括号, 都需要添加至少一个括号才能匹配
cut[l][r]意义同上
1 // Brackets sequence 2 // dynamic programming 3 4 #include <cstdio> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <iostream> 9 10 #define MAXN 100 11 12 int n, dp[MAXN+5][MAXN+5], cut[MAXN+5][MAXN+5]; 13 char s[MAXN+10]; 14 15 void PrintOut(int l, int r) 16 { 17 if(l > r) 18 return ; 19 if(l == r){ 20 if(s[l]=='('||s[l]==')') 21 printf("()"); 22 if(s[l]=='['||s[l]==']') 23 printf("[]"); 24 } 25 else{ 26 if(cut[l][r] >= 0){ 27 PrintOut(l, cut[l][r]); 28 PrintOut(cut[l][r]+1, r); 29 } 30 else{ 31 if(s[l]=='(' ){ 32 printf("("); 33 PrintOut(l+1, r-1); 34 printf(")"); 35 } 36 if(s[l]=='['){ 37 printf("["); 38 PrintOut(l+1, r-1); 39 printf("]"); 40 } 41 } 42 } 43 44 } 45 46 int main(int argc, char const *argv[]) 47 { 48 // freopen("in", "r", stdin); 49 50 while(gets(s)){ 51 52 memset(dp, 0, sizeof(dp)); 53 memset(cut, -1, sizeof(cut)); 54 55 for(int i = 0; i < strlen(s); ++i) 56 dp[i][i] = 1; 57 58 for(int len = 1; len < strlen(s); ++len){ 59 for(int l = 0; l+len < strlen(s); ++l){ 60 int r = l+len; 61 dp[l][r] = 1<<30; 62 if( (s[l]=='('&&s[r]==')')||(s[l]=='['&&s[r]==']') ) 63 dp[l][r] = std::min(dp[l][r], dp[l+1][r-1]); 64 else if(s[l]=='('||s[l]=='[') 65 dp[l][r] = std::min(dp[l][r], dp[l+1][r]+1); 66 else if(s[r]==')'||s[r]==']') 67 dp[l][r] = std::min(dp[l][r], dp[l][r-1]+1); 68 for(int m = l; m < r; ++m){ 69 if(dp[l][r] >= dp[l][m] + dp[m+1][r]){ 70 dp[l][r] = dp[l][m] + dp[m+1][r]; 71 cut[l][r] = m; 72 } 73 } 74 } 75 } 76 // printf("%d\n", dp[0][strlen(s)-1]); 77 PrintOut(0, strlen(s)-1); 78 printf("\n"); 79 } 80 return 0; 81 }