1. 程式人生 > >【日常刷題】最長括號匹配DP

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

最長括號匹配

這道題目看似可以使用棧來做,實則用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;
}