[中山市赛 2023] 永别题解
题目描述
你做了一个梦,梦里有一个字符串,这个字符串无论正着读还是倒着读都是一样的,例如:abcba 就符合这个条件。
但是你醒来时不记得梦中的字符串是什么,只记得它是另一个字符串 S 的子序列,你想知道梦中字符串最长是多少。
提示:字符串 A 是字符串 B 的子序列当且仅当从 B 中删除若干个字符(可以不删)后可以变成 A。例如:acd 是 achda 的子序列,因为从 achda 中删去第 3 个和第 5 个字符后就是 acd。
输入格式
第一行一个正整数 len,表示字符串 S 的长度。
第二行一个长度为 len 的字符串,表示字符串 S。
输出格式
第一行包含一个整数,表示梦中字符串最长的长度。
输入输出样例
输入 #1复制
7 acbdcaa
输出 #1复制
5
说明/提示
样例解释
从 acbdcaa 中删去第 4 个和第 7 个字符后变成 acbca 就满足正着读还是倒着读都是一样,不难发 现这是最长的。
数据范围
对于 15% 的数据,len≤20。
对于 30% 的数据,len≤200。
对于 45% 的数据,len≤700。
对于另外 15% 的数据,len≤800,字符串中只会出现字母 a 和 b。
对于 100% 的数据,3≤len≤1000,字符串中只会出现英文小写字母。
思路
区间DP,fij表示i~j中数量。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,f[3005][3005];
char a[3005];
int main(){
cin>>n;
//memset(f,62,sizeof(f));
for(int i=1;i<=n;i++){
cin>>a[i];
f[i][i]=1;
if(i!=1){
if(a[i]==a[i-1]){
f[i-1][i]=2;
}
else{
f[i-1][i]=1;
}
}
}
for(int i=3;i<=n;i++){
for(int l=1;l+i-1<=n;l++){
long long r=l+i-1;
if(a[l]==a[r]){
f[l][r]=f[l+1][r-1]+2;
}
else{
f[l][r]=f[l+1][r-1];
}
f[l][r]=max(f[l][r],max(f[l+1][r],f[l][r-1]));
}
}
cout<<f[1][n]<<endl;
return 0;
}

浙公网安备 33010602011771号