POJ 1159 Palindrome(字符串变回文:LCS)

来源:互联网 发布:ftp控制端口 编辑:程序博客网 时间:2024/05/16 10:48

POJ 1159 Palindrome(字符串变回文:LCS)

http://poj.org/problem?id=1159

题意:

       给你一个字符串, 问你做少需要在该字符串中插入几个字符能是的它变成一个回文串.

分析:

       首先把原字符串和它的逆串进行匹配, 找出最长公共子序列. 那么最长公共子序列的字符串肯定是一个回文串. 所以原串剩下的部分是不构成回文的. 我们只需要添加剩下部分的字符到对应位置, 原串自然就变成了一个回文.

       所以本题的解为: n 减去 (原串与逆串的LCS长度).

       令dp[i][j]==x表示串A的前i个字符与串B的前j个字符的子串的最长公共子序列LCS.

       初始化: dp全为0.

       状态转移:

       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[n][m].

       程序实现用的2维滚动数组, 如果用int[5000][5000]会超内存.

AC代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=5000+5;int n;char s1[maxn],s2[maxn];int dp[2][maxn];int main(){    while(scanf("%d",&n)==1)    {        scanf("%s",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%2][j]=dp[(i-1)%2][j-1]+1;            else                dp[i%2][j]=max(dp[(i-1)%2][j] , dp[i%2][j-1]);        }        printf("%d\n",n-dp[n%2][n]);    }    return 0;}

0 0
原创粉丝点击