Let us define a regular brackets sequence in the following way:
- Empty sequence is a regular sequence.
- If S is a regular sequence, then (S) and [S] are both regular sequences.
- If A and B are regular sequences, then AB is a regular sequence.
For example, all of the following sequences of characters are regular brackets sequences:
(), [], (()), ([]), ()[], ()[()]
And all of the following character sequences are not:
(, [, ), )(, ([)], ([(]
Some sequence of characters '(', ')', '[', and ']' is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1a2...an is called a subsequence of the string b1b2...bm, if there exist such indices 1 ≤ i1 < i2 < ... < in ≤ m, that aj=bij for all 1 ≤ j ≤ n.
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.
Output
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.
Sample Input
1 ([(]
Sample Output
()[()]
#include <cstdio> #include <cstring> #include <iostream> #include <string> #include <algorithm> using namespace std; // 原始表达式 char str[105]; //string str; // record[i][j]代表从i到j形成表达式需要添加的最小长度 int record[110][110]; // next[i][j]代表从i到j形成表达式时i配对的对应括号的位置 // 如果next[i][j]为-1代表自行添加,(,[,),]添加成(),[]. int next[110][110]; int get_len(int i, int j); void print_result(int begin, int end); int len; /* FILE* fp; FILE* fp2; */ void readline(char* S) { fgets(S, 105, stdin); } int main() { int n; // fp = fopen("1.txt", "r"); // fp2 = fopen("2.txt", "wr"); // scanf("%d", &n); /* cin >> n; char ch; while((ch=getchar()) != '\n') */ ; // fscanf(fp, "%d", &n); readline(str); sscanf(str, "%d", &n); readline(str); int count = 0; while(count < n) { memset(record, -1, sizeof(record)); // memset(next, -1, sizeof(next)); // memset(str, 0, sizeof(str)); // scanf("%s", str); // getline(cin, str); readline(str); len = strlen(str) - 1; // cout << "str:" << str << endl; // getline(cin, str); // cout << "str:" << str << endl; // fscanf(fp, "%s", str); // len = strlen(str); // len = str.length(); // 计算结果 // printf("result: %d\n", get_len(0, len-1)); // get_len(0, len-1); /* for(int i = 0; i < len; i++) { for(int j = i; j < len; j++) printf("result(%d,%d): %d\n", i, j, record[i][j]); } */ // 打印结果 if(count > 0) { printf("\n"); // fprintf(fp2, "\n"); } /* for(int i = 0; i < len; i++) printf("%c: %d\n", str[i], next[i]); */ print_result(0, len-1); printf("\n"); readline(str); count++; } /* fclose(fp); fclose(fp2); */ return 0; } // 计算结果 // 从i到j形成表达式需要添加的最小长度 int get_len(int i, int j) { // printf("here: record[%d][%d]\n", i, j); if(i > j) return 0; if(record[i][j] != -1) return record[i][j]; // printf("here: record[%d][%d]\n", i, j); if(i == j) { // next[i][i] = -1; record[i][j] = 1; // printf("here: record[%d][%d]: %d\n", i, j, record[i][j]); // printf("(%d,%d): %d\n", i, j, record[i][j]); return record[i][j]; } record[i][j] = len; /* char ch = '#'; if(str[i] == '(') ch = ')'; else if(str[i] == '[') ch = ']'; int result = 1 + get_len(i+1, j); if(result < record[i][j]) { record[i][j] = result; next[i][j] = -1; } for(int end = i+1; end <= j; end++) { if(str[end] == ch) { int result; result = 0; if(end - i > 1) result = get_len(i+1, end-1); if(j - end >= 1) result += get_len(end+1, j); if(result < record[i][j]) { record[i][j] = result; next[i][j] = end; } } } */ // int result = (1<<30); if(str[i] == '(' && str[j] == ')') { /* if(i+1 < j) result = get_len(i+1, j-1); else result = 0; */ record[i][j] = min(record[i][j], get_len(i+1,j-1)); } else if(str[i] == '[' && str[j] == ']') { /* if(i+1 < j) result = get_len(i+1, j-1); else result = 0; */ record[i][j] = min(record[i][j], get_len(i+1, j-1)); } /* if(result < record[i][j]) { record[i][j] = result; // next[i][j] = j; } */ for(int begin = i; begin <= j-1; begin++) { int result = get_len(i, begin) + get_len(begin+1, j); if(result < record[i][j]) record[i][j] = result; } return record[i][j]; } // 打印结果 void print_result(int begin, int end) { if(begin > end) return; // if(next[begin][end] == -1) if(begin == end) { if(str[begin] == '(' || str[begin] == ')') { printf("()"); // fprintf(fp2, "()"); } else { printf("[]"); // fprintf(fp2, "[]"); } return; /* if(begin+1 <= end) print_result(begin+1, end); */ } /* else if(((begin+1==end)||(record[begin][end] == record[begin+1][end-1]))&& ((str[begin]=='('&&str[end]==')')||(str[begin]=='['&&str[end]==']'))) */ int ans = get_len(begin, end); /* else if(record[begin][end]==record[begin+1][end-1] && ((str[begin]=='('&&str[end]==')')||(str[begin]=='['&&str[end]==']'))) */ if(ans == get_len(begin+1, end-1) && ((str[begin]=='('&&str[end]==')')||(str[begin]=='['&&str[end]==']'))) { printf("%c", str[begin]); // fprintf(fp2, "%c", str[begin]); /* int mid = next[begin][end]; if(begin+1 <= mid-1) print_result(begin+1, mid-1); printf("%c", str[mid]); // fprintf(fp2, "%c", str[mid]); if(mid+1 <= end) print_result(mid+1, end); */ // if(begin+1 <= end-1) print_result(begin+1, end-1); printf("%c", str[end]); return; } /* else { */ for(int i = begin; i <= end-1; i++) { if(ans == get_len(begin,i)+get_len(i+1,end)) { print_result(begin, i); print_result(i+1, end); return; } } /* } if(begin == 0 && end == len-1) { printf("\n"); // fprintf(fp2, "\n"); } */ }
这次代码写的很烂。思路错了,应该依照表达式构造方法来想。
分两种可能,如果S -> (S') 或者 [S'],检查S'
还有S -> AB,检查AB.