Palindrome

问题描述:给你一个字符串,问至少需要添加几个字符才能形成回文串。

in:

5
Ab3bd

out:

2

解释如:dAb3bAd

做法:将给出的字符串反向存一遍,然后找最长公共子序列,用原长减去该长度就是需要添加的字符数

由于长度n为[3,5000];开5000的二维数组会mle,所以我们用滚动数组,由于状态转移方程告诉我们,

如果a[i]==b[j] 则 dp[i][j]=dp[i-1][j-1]+1

如果a[i]!=b[j] 则 dp[i][j]=max(dp[i-1][j],dp[i][j-1])

dp[i][j]的状态只能从相邻的两行之间转移,所以保证了滚动数组的有效性,但这里也有一个奇怪的地方,如果用std::string存字符串会RE,一直没有想明白,还请路过的大佬提点

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]);

完整代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
char a[5050],b[5050];
int dp[2][5020];
int main()
{
    int n,i,j;
    while(~scanf("%d",&n))
    {
        j=0;
        //cin>>a;
        scanf("%s",&a);
        for(i=0; i<n; i++)
            b[j++]=a[n-1-i];
        for(i=0;i<n;i++)
        {
            for(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-dp[n%2][n]);
        //a.clear();
        //b.clear();
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(dp,0,sizeof(dp));
    }
    return 0;
}

 

原文地址:https://www.cnblogs.com/iloveysm/p/12270144.html