【日常刷题】最长括号匹配DP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ronaldo7_ZYB/article/details/83117069

最长括号匹配

这道题目看似可以使用栈来做,实则用DP可以更加简单。
我们设 f [ i ] f[i] 为以第i位结尾的可以匹配的最大长度。
对于每一个第 i i 位,如果需要存在合法序列必须满足两个条件
1.是左括号
2.必须和其有边的字符组成一个序列
事实上对于第一个条件我们只要简单的判断,而对于第二个条件就和我们的决策有关。
而对于转移方程f[i],只要当前的这个字符 s [ i ] s[i] 和以 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])
对于条件3,我们只要继续累加 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;
}

猜你喜欢

转载自blog.csdn.net/Ronaldo7_ZYB/article/details/83117069