Appoint description:
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
()[()]
题意:
给出一个由 ( ) [ ] 四种符号组成的串,问要把这个串变成括号匹配串后的最短串是什么样。
struct node
{
int t;
string now;
}
用 dp[i][j].t 来记录区间 i~j 所需要的最小数目,dp[i][j].now 记录区间 i~j 这个区间变成匹配区间之后的样子。
若 s[i] == s[j] 那么 dp[i][j].t = min(dp[i][j].t,dp[i+1][j-1].t);
枚举i~j中间的断点k 有 dp[i][j].t = min(dp[i][j].t , dp[i][k].t + dp[k+1][j].t);
然后对于每次转移的由来将对应区间的 now 做出对应改变。
注意坑点是虽然题目没说,但是输入的字符串可能是包含空格的(估计是标程都错了导致样例有问题)。对于空格也应该输出一对括号来匹配。
#include"iostream"
#include"cstring"
#include"cstdio"
#include"algorithm"
#include"string"
#define INF 0x7fffffff
using namespace std;
struct node
{
int t;
string now;
};
char sc[105];
string ss;
node dp[105][105];
bool check(char a,char b)
{
if(a == '(' && b == ')') return true;
if(a == '[' && b == ']') return true;
return false;
}
void init(int siz)
{
for(int i = 0;i < siz;i++)
{
for(int j = i;j < siz;j++)
{
dp[i][j].now = "";
dp[i][j].t = INF;
}
}
for(int i = 0;i < siz;i++)
{
dp[i][i].t = 1;
if(ss[i] == '(' || ss[i] == ')')
dp[i][i].now = "()";
else dp[i][i].now = "[]";
}
}
int main(void)
{
while(gets(sc))
{
ss = sc;
int siz = ss.size();
init(siz);
for(int i = siz-1;i >= 0;i--)
{
for(int j = i+1;j < siz;j++)
{
if(check(ss[i],ss[j]))
{
if(dp[i+1][j-1].t < dp[i][j].t)
{
dp[i][j].t = dp[i+1][j-1].t;
dp[i][j].now = ss[i] + dp[i+1][j-1].now + ss[j];
}
}
for(int k = i;k < j;k++)
{
if(dp[i][j].t > dp[i][k].t + dp[k+1][j].t)
{
dp[i][j].t = dp[i][k].t + dp[k+1][j].t;
dp[i][j].now = dp[i][k].now + dp[k+1][j].now;
}
}
}
}
cout << dp[0][siz-1].now << endl;
}
return 0;
}