トピックリンク:
http://poj.org/problem?id=1141
ブラケットシーケンス
制限時間: 1000MS | メモリ制限: 65536K | |||
提出総数: 32282 | 承認済み: 9321 | 特別裁判官 |
説明
次の方法で通常のブラケットシーケンスを定義しましょう
。1。空のシーケンスは通常のシーケンスです。
2. Sが正則列の場合、(S)と[S]は両方とも正則列です。
3. AとBが正則列の場合、ABは正則列です。
たとえば、次の文字シーケンスはすべて通常の角かっこシーケンスです:
()、[]、(())、([])、()[]、()[()]
そして次の文字シーケンスはすべてない:
(、[、)、)(、([)]、([(]
文字のシーケンス '('、 ')'、 '['、および ']'が指定されています。指定された文字シーケンスをサブシーケンスとして含む、可能な限り短い通常のブラケットシーケンスを見つける必要があります。ここで、文字列a1 a2 ... anは、文字列b1 b2 ... bmのサブシーケンスと呼ばれ、そのようなインデックス1 = i1 <i2 <... <in = mが存在する場合、すべての1に対してaj = bijとなります。 = j = n。
。1。空のシーケンスは通常のシーケンスです。
2. Sが正則列の場合、(S)と[S]は両方とも正則列です。
3. AとBが正則列の場合、ABは正則列です。
たとえば、次の文字シーケンスはすべて通常の角かっこシーケンスです:
()、[]、(())、([])、()[]、()[()]
そして次の文字シーケンスはすべてない:
(、[、)、)(、([)]、([(]
文字のシーケンス '('、 ')'、 '['、および ']'が指定されています。指定された文字シーケンスをサブシーケンスとして含む、可能な限り短い通常のブラケットシーケンスを見つける必要があります。ここで、文字列a1 a2 ... anは、文字列b1 b2 ... bmのサブシーケンスと呼ばれ、そのようなインデックス1 = i1 <i2 <... <in = mが存在する場合、すべての1に対してaj = bijとなります。 = j = n。
入力
入力ファイルには、最大100個の角かっこ(文字 '('、 ')'、 '['、および ']')が含まれ、それらは1行にあり、他の文字は含まれていません。
出力
可能な限り最小の長さを持ち、サブシーケンスとして指定されたシーケンスを含むいくつかの通常のブラケットシーケンスを含む1行を出力ファイルに書き込みます。
サンプル入力
([(]
サンプル出力
()[()]
//区间DP
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 1005
#define inf 0x3f3f3f3f
using namespace std;
char s[maxn];
int dp[maxn][maxn]; //dp[i][j]表示区间i~j内需要最少的字符数能够匹配
int path[maxn][maxn]; //path[i][j]是表示怎么达到dp[i][j]状态的
int peidui(char c1, char c2)
{
if((c1=='(' && c2==')')||(c1=='['&&c2==']'))
return 1;
return 0;
}
//输出区间(x,y)的配对结果
void print_path(int x, int y)
{
if(x>y)
return;
//只剩下一个,补上完整的
if(x==y)
{
if(s[x]=='(' || s[x]==')')
printf("()");
else
printf("[]");
return;
}
if(path[x][y]==-1) //s[x]和s[y]配对
{
printf("%c", s[x]);
print_path(x+1, y-1);
printf("%c", s[y]);
}
else
{
int k = path[x][y];
print_path(x, k);
print_path(k+1, y);
}
}
int main()
{
while(gets(s))
{
memset(dp, 0, sizeof(dp));
int l = strlen(s);
for(int i=0; i<l; i++) //单个字符需要1个
dp[i][i] = 1;
for(int len=1; len<l; len++)
for(int i=0; i<l-len; i++)
{
int j = i+len;
dp[i][j] = inf;
if(peidui(s[i], s[j]))
{
if(dp[i+1][j-1]<dp[i][j])
{
dp[i][j] = dp[i+1][j-1];
path[i][j] = -1;
}
}
for(int k=i; k<j; k++)
{
if(dp[i][k]+dp[k+1][j] < dp[i][j])
{
dp[i][j] = dp[i][k]+dp[k+1][j];
path[i][j] = k;
}
}
}
print_path(0, l-1);
printf("\n");
}
return 0;
}