◇区间动态规划◇ Brackets Sequence
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.
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
()[()]
题目大意
给出一个括号序列(最长长度100),包含 “[]” 和 “()” 。插入最少的括号,使序列中的括号全部匹配,注意——”[(])” 不认为是匹配的。输出这个序列,题目设置有 Special judge,可输出任何一个答案。
题目解析
对于任意一个区间DP,它的状态定义都是:
g[x][y]表示在原序列中第x到第y个元素的答案;
或者,g[x][y]表示在原序列中从第x个元素开始的y个元素的答案;
然后便是状态转移方程式,由于数组g无法同时保存字符串,因此只能保存最少添加的括号数量。分2种情况——
- 当前第x个字符与第y个字符匹配
- 当前第x个字符与第y个字符不匹配
通过假设:
设A、B都为完全匹配的括号序列,则AB和 (A)、(B)、[A]、[B] 也是完全匹配的括号序列。
我们可以证出针对情况1的 g[x][y] 应该等于 g[x+1][y-1] ,即忽略当前的位置,计算把中间的序列变成完全匹配的括号序列需要多少次。但是这并不意味着遇到情况1时就不考虑情况2,给出一个简单的反例—— “()()”。若只考虑情况1,则针对 “)(“就会得到2,但是正确答案是0。接下来就考虑情况2,也就是 AB 的情况。我们需要把原串变成 AB 的形式,也就是在某一个点分为2份,因此枚举k,分割为 x~k 和 k+1~y 的两个区间。
最后是设置边界,当 x==y 时,也就是只剩下一个字符时(例如”(” 和 “]”),只能添加一个括号,即返回1。
输出方案则是通过递归,详见程序(不要说作者懒)。
程序样例
/*Lucky_Glass*/
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
string s;
bool f[105][105];
int g[105][105];
int G(int x,int y)
{
if(x>y) return 0;
if(x==y) return g[x][y]=1;
if(f[x][y]) return g[x][y];
f[x][y]=true;
if((s[x]=='(' && s[y]==')') || (s[x]=='[' && s[y]==']')) g[x][y]=G(x+1,y-1);
else g[x][y]=y-x+5;
for(int i=x;i<y;i++)
g[x][y]=min(g[x][y],G(x,i)+G(i+1,y));
return g[x][y];
}
void VJudge(int x,int y)
{
if(x>y) return;
if(x==y)
{
if(s[x]=='(' || s[y]==')') printf("()");
else printf("[]");
return;
}
for(int i=x;i<y;i++)
if(g[x][y]==g[x][i]+g[i+1][y])
{
VJudge(x,i),VJudge(i+1,y);
return ;
}
if(g[x][y]==g[x+1][y-1] && (s[x]=='(' && s[y]==')') || (s[x]=='[' && s[y]==']')) printf("%c",s[x]),VJudge(x+1,y-1),printf("%c",s[y]);
}
int main()
{
cin>>s;
G(0,(int)s.length()-1);
VJudge(0,(int)s.length()-1);
printf("\n");
return 0;
}
The End
Thanks for reading!
-Lucky_Glass