1 解题思路
这道题我们可以把整个字符串的大区间拆分成小区间,然后让相邻的两个小区间拼起来,如果左边小区间的第一个字符和右边小区的的最后一个字符相同,就可以选择它俩,再加上他们之间的字符能构成回文串的最大长度;如果不同,就选左边小区间和右边小区间的较大者。
这就不难想到区间dp: d p l r dplr dplr表示区间 l , r l,r l,r的字符串构成的最长回文串的长度。初始化全部元素为0, d p i i = 1 dpii=1 dpii=1。三种循环,第一层枚举区间长度,第二层枚举左右区间端点,第三层枚举区间的切割点(大区间切割成两个小区间,按照前面的策略更新 d p dp dp值)。
2 AC Code
cpp
#include<bits/stdc++.h>
using namespace std;
int n,dp[1005][1005];
string s;
int main(){
cin>>n;
cin>>s;
for(int i=1;i<=n;i++) dp[i][i]=1;
for(int lenn=2;lenn<=n;lenn++){
for(int l=1,r=l+lenn-1;r<=n;l++,r++){
if(s[l-1]==s[r-1]){
if(r-l<=1) dp[l][r]=2;
else dp[l][r]=max(dp[l][r],2+dp[l+1][r-1]);
}
for(int k=l;k<r;k++)
dp[l][r]=max(dp[l][r],max(dp[l][k],dp[k+1][r]));
}
}
cout<<dp[1][n];
return 0;
}