POJ2955

求给定序列匹配括号的最大子列

令dp[ i ][ j ]表示i到j中匹配的最大子列的长度

初始化 dp[ i ][ i ] = 0

那么

1.dp[ i ][ j ] = dp[ i ][ j-1 ],如果第j个括号是左括号,则不可能与之前的括号匹配,所以最大匹配子列长度不变

2.dp[ i ][ j ] = max(dp[ i ][ j-1 ],max( dp[ i ][ k -1 ] + dp[ k+1 ][ j -1 ] +2)),如果是右括号

我们来着重讨论这个右括号的情况,

求dp[i][j]时,第j个括号是右括号无非会导致两种情况

1.第j个括号不匹配

2.第j个括号与第i~j-1个括号中的一个相匹配

如果第j个括号不匹配,实际上与情况1一致,这就出现了上面max中的第一项

如果第j个括号匹配i~j-1中的某个编号为k的括号,那么dp[i][j]表示第i到第j匹配的最大子列长度就表示为

第i到第k-1位匹配的最大子列长度+第k+1到j-1位匹配的最大子列长度+2(匹配的第j和第k位括号贡献的长度)

要找到能使dp[i][j]最大的那个k

这就是上面max中第二项的解释

#include<iostream>
#include<string>
#include<memory.h>
using namespace std;
int dp[101][101];
int main()
{
    char s[102];
    cin.getline(s,101);
    while(strcmp(s,"end"))
    {
        int len=1;
        while(s[len]!='\0'){
            len++;
        }
        for(int i=len;i>=1;i--){
            s[i]=s[i-1];
        }
        memset(dp,0,sizeof(dp));
        for(int j=2;j<=len;j++){
            for(int i=j-1;i>=1;i--){
                dp[i][j]=dp[i][j-1];
                if(s[j]=='['||s[j]=='('){
                    continue;
                }
                else{
                    for(int k=i;k<j;k++){
                        if((s[k]=='['&&s[j]==']')||(s[j]==')'&&s[k]=='(')){
                            dp[i][j]=max(2+dp[i][k-1]+dp[k+1][j-1],dp[i][j]);
                        }
                    }
                }
            }
        }
        cout<<dp[1][len]<<endl;
        cin.getline(s,101);
    }
}



猜你喜欢

转载自blog.csdn.net/luo3300612/article/details/78476189
今日推荐