【日常刷題】最長括號匹配DP

最長括號匹配

這道題目看似可以使用棧來做,實則用DP可以更加簡單。
我們設f[i]f[i]爲以第i位結尾的可以匹配的最大長度。
對於每一個第ii位,如果需要存在合法序列必須滿足兩個條件
1.是左括號
2.必須和其有邊的字符組成一個序列
事實上對於第一個條件我們只要簡單的判斷,而對於第二個條件就和我們的決策有關。
而對於轉移方程f[i],只要當前的這個字符s[i]s[i]和以i+1i+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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章