Brackets Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 23551 | Accepted: 6647 | Special Judge |
Description
Let us define a regular brackets sequence in the following way:
1. Empty sequence is a regular sequence.
2. If S is a regular sequence, then (S) and [S] are both regular sequences.
3. 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 a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.
1. Empty sequence is a regular sequence.
2. If S is a regular sequence, then (S) and [S] are both regular sequences.
3. 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 a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.
Input
The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.
Output
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
([(]
Sample Output
()[()]
首先说,我对输方案目前阶段还有阴影,所以纠缠这道题很久……
不过仔细分析其实多简单的。
首先,分析如果不让输方案而是输添加括号的个数该怎么办:(觉得这个问题很弱的可以直接跳到空行的后面……顺便orz)
典型区间dp
f[i][j]表示区间i到j的串合法要添加的括号数
那么 转移方程:
1.如果c[i]和c[j]恰好是一对括号,那么: f[i][j] =min(f[i][j] , f[i + 1][j - 1])
2.否则 f[i][j] = min(f[i][j] ,f[i][k] + f[k + 1][j];
然后是要注意边界—— i==j 时 f[i][j] = 1;
接下来终于该考虑输出方案的问题了:
显而易见,只有我们知道了f[i][j]是从那里转移过来的我们就知道怎么加括号了(用g[i][j]记录)
如果是从第一种情况转移来那么应该是输出 :‘(’ + [i+1]到[j-1]的情况 + ‘)’
如果是从第二种情况转移来那么应该是输出 :i 到 g[i][j] 的情况 链接上 g[i][j]+1到r的情况
这个显而易见是用递归很好实现的
注意poj的读入有空行,所以用gets读入
还要特判读入的是不是空字符串哦!!!
#include <iostream>
#include <cstring>
#include <string.h>
#include <cstdio>
using namespace std;
const long N = 120;
char c[120];
long f[120][120];
long g[120][120];
long n;
void prt(long l, long r)
{
if (r == l)
{
if ((c[l] == '(') || (c[l] == ')')) printf("()");
if ((c[l] == '[') || (c[l] == ']')) printf("[]");
return ;
}
if (g[l][r] == -1)
{
if ( (c[l] == '(') && (c[r] == ')') )
{
printf("(");
prt(l + 1, r - 1);
printf(")");
}
if ( (c[l] == '[') && (c[r] == ']') )
{
printf("[");
prt(l + 1, r - 1);
printf("]");
}
}
else{
prt(l, g[l][r]);
prt(g[l][r] + 1, r);
}
}
void dp()
{
n = strlen(c);
memset(f, 127, sizeof(f));
memset(g, -1, sizeof(g));
for (long i = 0; i < n; i++)
{
f[i][i] = 1;
}
for (long l = 2; l <= n; l++)
{
for (long i =0; i + l - 1 < n; i++)
{
long j = i + l - 1;
if (((c[i] == '[') && (c[j] == ']')) || ((c[i] == '(') && (c[j] == ')')))
{
if (i + 1 == j) f[i][j] =0;
if (f[i][j] > f[i + 1][j - 1])
{
f[i][j] = f[i + 1][j - 1];
}
}
for (long k = i; k < j; k++)
{
if (f[i][j] > f[i][k] + f[k + 1][j])
{
f[i][j] = f[i][k] + f[k + 1][j];
g[i][j] = k;
}
}
}
}
//cout << f[0][n - 1] << endl;
}
int main()
{
freopen("poj1141.in", "r", stdin);
while (gets(c))
{
if (strlen(c) == 0)
{
printf("\n");
continue;
}
dp();
prt(0, n - 1);
printf("\n");
}
return 0;
}