HDU 1513[Palindrome] 回文串

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513

题目大意:给一个字符串,问最少加多少个字母能成为回文串。

关键思想:要解决的是回文子序列问题而不是回文子串。回文子序列怎么求?可以把字符串倒转一下,再求他们的最长公共子序列啊!想一想为什么。求出LCS长度之后,n-LCS才是我们要的答案,因为对于不是回文子序列的其他字符来说,都需要给他们一个对象才能回文(对称)。还有一个问题是我们开不了5000*5000的数组,但观察到递推方程是只与两个状态有关,

i的n-1态和i的n态,而j的n-1态在遍历的时候可以得到。也就是说,我们只要2*5000就能达到要求了。这就是滚动数组,轮流成为现态。

代码如下:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
using namespace std;
const int MAXN=5050;

int c[2][MAXN];

int LCS(string a,string b){
    memset(c,0,sizeof(c));
    for(int i=1;i<=a.size();i++){
        for(int j=1;j<=b.size();j++){
            if(a[i-1]==b[j-1]){
                c[i&1][j]=c[1-i&1][j-1]+1;//如果是奇数用c[1],否则用c[2]    
            }
            else{
                c[i&1][j]=max(c[i&1][j-1],c[1-i&1][j]);    
            }
        }
    }
    return c[a.size()&1][b.size()];
    //注意下标,c[i][j]表示A[0,i-1]和B[0,j-1]的LCS长度 
}

int main(){
    int n;
    string a,ra;
    while(cin>>n>>a){//多组输入输出,潜规则 
        ra=a;
        reverse(ra.begin(),ra.end());//反转一下 
        cout<<n-LCS(a,ra)<<endl;//除了回文子序列,其他的都需要一个对象     
    }
    return 0;
}

 

posted @ 2017-08-12 20:24  哇咔咔咔  阅读(272)  评论(0编辑  收藏  举报