UVa11404

来源:互联网 发布:淘宝进口商品资质 编辑:程序博客网 时间:2024/06/07 18:33

题目链接

简介:
删除若干个字符,使字符串变成回文字符串

分析:
之前就已经说过,回文字符串的长度就等价于把字符串翻转之后求一个LCS
但是这道题的难点在于方案输出:
我们要怎么找到字典序最小的方案呢?

我们用string解决这个问题,在转移的时候同时维护字典序最小的LCS

if (a[i-1]==b[j-1]){    f[i][j].len=f[i-1][j-1].len+1;    f[i][j].s=f[i-1][j-1].s+a[i-1];}     else    {        if (f[i][j-1].len>f[i-1][j].len)            f[i][j]=f[i][j-1];          else if (f[i-1][j].len>f[i][j-1].len)            f[i][j]=f[i-1][j];        else        {            f[i][j].len=f[i-1][j].len;            f[i][j]=s=min(f[i-1][j].s,f[i][j-1].s);       //字典序最小         }   } 

因为string重载过运算符,所以写起来舒服一点

最后方案输出的时候,要注意一点

f[n][n].s不一定是最后的答案,因为f[n][n].s不一定是回文

例如:
kfcl bc k ibbib j c bej
je bc jb ibbi kc b l c fk

bcibbibc是他们的LCS,但是却不是回文串
最后的答案是bcibbicb

可以发现,求出的s 前len/2 个一定是回文串的前半部分
知道了前len/2,就可以直接构造出回文串的后半部分了

要注意最后的答案奇偶不同,构造方法也有一点不一样

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<string>using namespace std;const int N=1003;struct node{    int len;    string s;};node f[N][N];char a[N],b[N];int n;void doit(){    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            if (a[i-1]==b[j-1])            {                f[i][j].len=f[i-1][j-1].len+1;                f[i][j].s=f[i-1][j-1].s+a[i-1];            }             else            {                if (f[i][j-1].len>f[i-1][j].len)                    f[i][j]=f[i][j-1];                  else if (f[i-1][j].len>f[i][j-1].len)                    f[i][j]=f[i-1][j];                else                {                    f[i][j].len=f[i-1][j].len;                    f[i][j].s=min(f[i-1][j].s,f[i][j-1].s);       //字典序最小                 }               } }int main(){    while (scanf("%s",&a)!=EOF)    {        n=strlen(a);        for (int i=0;i<n;i++)            b[n-i-1]=a[i];        for (int i=0;i<=n;i++)            f[0][i].len=0,f[0][i].s="";        doit();        int ans=f[n][n].len;        string c=f[n][n].s;        if (ans&1)        {            for (int i=0;i<ans/2;i++) cout<<c[i];            for (int i=ans/2;i>=0;i--) cout<<c[i];        }        else        {            for (int i=0;i<ans/2;i++) cout<<c[i];            for (int i=ans/2-1;i>=0;i--) cout<<c[i];        }        printf("\n");    }    return 0;}
原创粉丝点击