题目大意:
给你一串字符序列,问序列中可以匹配的括号最多有多少个;
解题思路:
首先需要注意,最多可以匹配的括号个数,如果可以匹配一对括号,那么个数为2,‘(’和‘)’或者‘【’和‘】’;
我们用dp[i][j]表示【i,j】这个区间内可以匹配的最大的括号数;
则有转移方程
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]);
在进行这个判断的时候需要判断i,j是否匹配,如果匹配的话dp【i】【j】=dp【i+1】【j-1】+2;如果没有这个特判,那么转移方程是无法处理这种情况的;
有的人会疑问为什么有k会出现在俩个区间中呢?k如果匹配前一个区间,那么必然不会匹配后一个区间;反之亦然,如果不共用k,可能少情况,所以我们要共用k,处理这种情况;
代码我给出了俩种形式,我个人觉得,因为这种匹配没有牵扯到共用字符的情况,所以俩种形式的代码才可以都通过;
第一种形式的代码
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
string s;
while(cin>>s)
{
if(s=="end") break;
int dp[110][110];
memset(dp,0,sizeof(dp));
int len=s.length();
for(int i=len-2;i>=0;i--)
for(int j=i+1;j<len;j++)
{
if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
dp[i][j]=dp[i+1][j-1]+2;
for(int k=i+1;k<j;k++)
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]);
}
cout<<dp[0][len-1]<<endl;
}
}
第二种形式的代码
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
string s;
while(cin>>s)
{
if(s=="end") break;
int dp[110][110];
memset(dp,0,sizeof(dp));
int len=s.length();
for(int r=1;r<len;r++)
for(int i=0;i+r<len;i++)
{
int j=i+r;
if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
dp[i][j]=dp[i+1][j-1]+2;
for(int k=i+1;k<j;k++)
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]);
}
cout<<dp[0][len-1]<<endl;
}
}