最长括号匹配
这道题目看似可以使用栈来做,实则用DP可以更加简单。
我们设
f
[
i
]
f[i]
f[i]为以第i位结尾的可以匹配的最大长度。
对于每一个第
i
i
i位,如果需要存在合法序列必须满足两个条件
1.是左括号
2.必须和其有边的字符组成一个序列
事实上对于第一个条件我们只要简单的判断,而对于第二个条件就和我们的决策有关。
而对于转移方程f[i],只要当前的这个字符
s
[
i
]
s[i]
s[i]和以
i
+
1
i+1
i+1位起点构成串的有边匹配,就说明能够成立一个合法的串。如果列出转移方程,就是:
f
[
i
]
=
f
[
i
+
1
]
+
2
,
(
s
[
i
]
属
于
左
括
号
,
s
[
i
]
=
s
[
i
+
f
[
i
]
+
1
]
)
f[i]=f[i+1]+2,(s[i]属于左括号, s[i]=s[i+f[i]+1])
f[i]=f[i+1]+2,(s[i]属于左括号,s[i]=s[i+f[i]+1])
对于条件3,我们只要继续累加
f
[
i
+
f
[
i
]
]
f[i+f[i]]
f[i+f[i]]即可。
CODE
#include<bits/stdc++.h>
using namespace std;
#define MAXN 2000000
int MAX=0,st=0,f[MAXN];
char s[MAXN];;
int main()
{
cin>>s;
int len=strlen(s);
for (int i=len-1;i>=0;--i)
{
if (s[i]==')' || s[i]==']') continue;//右括号不合法
if ((s[i]=='(' && s[i+f[i+1]+1]==')') || (s[i]=='[' && s[i+f[i+1]+1]==']'))//存在对顶的字符串
{
f[i]=f[i+1]+2;//上一个决策加上新的收尾
f[i]+=f[i+f[i]];//满足条件3,即多个不同的串进行累加
if (f[i]>=MAX) MAX=f[i],st=i;
}
}
for (int i=0;i<MAX;i++) cout<<s[st+i];
return 0;
}