POJ - 1159 Palindrome(最长公共子序列---空间压缩(滚动数组))

题目链接:https://cn.vjudge.net/contest/312755#problem/B

题意:给你一个数N,表示字符串的长度,接着一个字符串,找需要拼凑出回文串的最小增加个数

思路:倒着把数组存一遍,找到两个字符串的最长公共子序列(LCS),字符串的长度减去LCS的长度,就是所求结果。

LCS解析:
s 1 s 2 . . . . . . s n 的 子 序 列 可 以 表 示 为 S i 1 S i 2 . . . . . . S i m ( i 1 < i 2 < . . . . . < i m ) − − − − − − − − − > ∗ ∗ 子 序 列 不 一 定 是 连 续 的 ∗ ∗ s_1s_2......s_n的子序列可以表示为S_{i1} S_{i2}...... S{im}(i1<i2<.....<im)--------->**子序列不一定是连续的** s1s2......snSi1Si2......Simi1<i2<.....<im>

s = “ a b c d ” ; t = “ b e c d ” s=“abcd”;t=“becd” s=abcd;t=becd
对应下表的各种情况(空白位置表示的是0)
在这里插入图片描述
dp[i][j]:=s1…si和t1…tj对应的LCS的长度
把上表赋予意义,就能得出递推关系式

d p [ i + 1 ] [ j + 1 ] = m a x ( d p [ i ] [ j ] + 1 , d p [ i ] [ j + 1 ] , d p [ i + 1 ] [ j ] ) ( S i + 1 = t j + 1 时 ) ∣ ∣ m a x ( d p [ i ] [ j + 1 ] , d p [ i + 1 ] [ j ] ) ( 其 他 ) dp[i+1][j+1]=max(dp[i][j]+1,dp[i][j+1],dp[i+1][j])(S_{i+1}=t_{j+1}时)| |max(dp[i][j+1],dp[i+1][j])(其他) dp[i+1][j+1]=max(dp[i][j]+1,dp[i][j+1],dp[i+1][j])(Si+1=tj+1)max(dp[i][j+1],dp[i+1][j])()
此时的空间用了4*4的二维数组

优化:
dp就用两行表示状态,dp[2][N]

for(int i=0; i<N; i++){
        for(int j=0; j<N; j++){
            if(a[i]==b[j])
                dp[(i+1)%2][j+1]=dp[i%2][j]+1;
            else
                dp[(i+1)%2][j+1]=max(dp[i%2][j+1],dp[(i+1)%2][j]);
        }
    }

例如:
s=“Ab3bd”
t=“db3bA”

i=0时,(j=0~4)
d p [ 1 ] [ 1 ] = m a x ( d p [ 0 ] [ 1 ] , d p [ 1 ] [ 0 ] ) = 0 ; dp[1][1]=max(dp[0][1],dp[1][0])=0; dp[1][1]=max(dp[0][1],dp[1][0])=0;
d p [ 1 ] [ 2 ] = m a x ( d p [ 0 ] [ 2 ] , d p [ 1 ] [ 1 ] ) = 0 ; dp[1][2]=max(dp[0][2],dp[1][1])=0; dp[1][2]=max(dp[0][2],dp[1][1])=0;
d p [ 1 ] [ 3 ] = m a x ( d p [ 0 ] [ 3 ] , d p [ 1 ] [ 2 ] ) = 0 ; dp[1][3]=max(dp[0][3],dp[1][2])=0; dp[1][3]=max(dp[0][3],dp[1][2])=0;
d p [ 1 ] [ 4 ] = m a x ( d p [ 0 ] [ 4 ] , d p [ 1 ] [ 3 ] ) = 0 ; dp[1][4]=max(dp[0][4],dp[1][3])=0; dp[1][4]=max(dp[0][4],dp[1][3])=0;
d p [ 1 ] [ 5 ] = d p [ 0 ] [ 4 ] + 1 = 1 ; dp[1][5]=dp[0][4]+1=1; dp[1][5]=dp[0][4]+1=1;$
i=2时,(j=0~4)
$dp[0][1]=max(dp[1][1],dp[0][0])=0 $
/ / d p [ 1 ] 时 前 一 个 状 态 , d p [ 1 ] [ 1 ] 表 示 s = A , t = d 。 //dp[1]时前一个状态,dp[1][1]表示s=A,t=d。 //dp[1]dp[1][1]s=At=d

d p [ 0 ] [ 2 ] = d p [ 1 ] [ 2 ] + 1 = 1 ; dp[0][2]=dp[1][2]+1=1; dp[0][2]=dp[1][2]+1=1;

dp[0][3]=max(dp[1][3],dp[0][2])=1
//dp[1][3]表示前一个字母A遍历到j=2处,dp[0][2]表示字母b遍历到j-1处
dp[0][4]=max(dp[1][4],dp[0][3])=1;
dp[0][5]=max(dp[1][5],dp[0][4])=1;
i=3时,(j=0~4)
dp[1][1]=max(dp[1][0],dp[0][1])=0;
dp[1][2]=max(dp[1][1],dp[0][2])=1;//dp[1][2]更新为1,i=0时的dp[1][2]滚动到这里,并更新为1
dp[1][3]=dp[0][2]+1=2;//dp[1][3]更新为2
dp[1][4]=max(dp[1][3],dp[0][4])=1;//dp[1][4]更新为1
dp[1][5]=max(dp[1][4],dp[0][5])=1;//dp[1][5]更新为1

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,k;
char a[5020],b[5020];
int dp[5][5020];
int main(){
    scanf("%d",&N);
    k=0;
    memset(dp,0,sizeof(dp));
    scanf("%s",a);
    for(int i=N-1; i>=0; i--)
        b[k++]=a[i];
    for(int i=0; i<N; i++){
        for(int j=0; j<N; j++){
            if(a[i]==b[j])
                dp[(i+1)%2][j+1]=dp[i%2][j]+1;
            else
                dp[(i+1)%2][j+1]=max(dp[i%2][j+1],dp[(i+1)%2][j]);
        }
    }
    printf("%d\n",N-dp[N%2][N]);
    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值