POJ2955

来源:互联网 发布:asp公司网站源码 编辑:程序博客网 时间:2024/05/16 17:18

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

令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);    }}



原创粉丝点击