求最长回文自序列经典做法 反转目标串求lcs
dp方程: s[i]==s[j]:dp[i][j]=dp[i+1][j-1]+1
else dp[i][j]=max(dp[i+1][j],dp[i][j-1])
其中 下标i,j表示从i到j的最大公共子序列
但是这样做会需要开dp[5000][5000]--mle
所以要只保存当前状态 和 前一状态 也就是i-1态
这个做法和概率dp有点相似的
下标表示是 i&1
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 5555
char s1[maxn],s2[maxn];
int dp[2][maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
scanf("%s",s1);
strcpy(s2,s1);
for(int i=0;i<n;++i)
s2[i]=s1[n-1-i];
memset(dp,0,sizeof dp);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(s1[i-1]==s2[j-1])
dp[i&1][j]=dp[(i-1)&1][j-1]+1;
else
dp[i&1][j]=max(dp[(i-1)&1][j],dp[i&1][j-1]);
printf("%d\n",n-dp[n&1][n]);
}
return 0;
}