[中山市赛 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;
}

posted @ 2025-10-14 21:13  bz02_2023f2  阅读(9)  评论(0)    收藏  举报  来源