UVa11404 - Palindromic Subsequence(区间DP+打印路径)

题目大意

给定一个字符串,要求你删除尽量少的字符,使得原字符串变为最长回文串,并把回文串输出,如果答案有多种,则输出字典序最小的

题解

有两种解法,第一种是把字符串逆序,然后求两个字符串的LCS,并记录LCS,长度就等于最长回文串的长度,不过求出来的LCS不一定是回文串,例如下面这个例子

        s  = 1 5 2 4 3 3 2 4 5 1

reverse(s) = 1 5 4 2 3 3 4 2 5 1

       LCS = 1 5 2   3 3   4 5 1
所以我们只需要LCS的前半段即可

代码:

#include <cstdio>

#include <algorithm>

#include <string>

#include <iostream>

#include <utility>

using namespace std;

#define MAXN 1005

string a,b;

pair<int,string>dp[MAXN][MAXN];

int main()

{

    while(cin>>a)

    {

        int len=a.length();

        b=a;

        reverse(b.begin(),b.end());

        for(int i=0;i<len;i++)

        {

            dp[0][i].first=0,dp[0][i].second="";

            dp[i][0].first=0,dp[i][0].second="";

        }

        for(int i=0;i<len;i++)

            for (int j=0;j<len;j++)

                if(a[i]==b[j])

                {

                    dp[i+1][j+1].first=dp[i][j].first+1;

                    dp[i+1][j+1].second=dp[i][j].second+a[i];

                }

                else

                {

                    if(dp[i+1][j].first>dp[i][j+1].first)

                    {

                        dp[i+1][j+1].first=dp[i+1][j].first;

                        dp[i+1][j+1].second=dp[i+1][j].second;

                    }

                    else

                        if(dp[i+1][j].first==dp[i][j+1].first)

                        {

                            dp[i+1][j+1].first=dp[i][j+1].first;

                            dp[i+1][j+1].second=min(dp[i][j+1].second,dp[i+1][j].second);

                        }

                        else

                        {

                            dp[i+1][j+1].first=dp[i][j+1].first;

                            dp[i+1][j+1].second=dp[i][j+1].second;

                        }

                }

                int lens=dp[len][len].first;

                string s=dp[len][len].second;

                if(lens&1)

                {

                    int t=lens/2;

                    for(int i=0;i<=t;i++)

                        cout<<s[i];

                    for(int i=t-1;i>=0;i--)

                        cout<<s[i];

                    cout<<endl;

                }

                else

                {

                    int t=lens/2;

                    for(int i=0;i<t;i++)

                        cout<<s[i];

                    for(int i=t-1;i>=0;i--)

                        cout<<s[i];

                    cout<<endl;

                }

    }

    return 0;

}

第二种方法和POJ1159一样,不过是多了个路径而已

代码:

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <iostream>

#include <string>

using namespace std;

#define MAXN 1005

string s;

int dp[MAXN][MAXN];

string path[MAXN][MAXN];

int main()

{

    int n;

    while(cin>>s)

    {

        memset(dp,0,sizeof(dp));

        int n=s.length();

        for(int i=n-1; i>=0; i--)

            for(int j=i; j<n; j++)

                if(s[i]==s[j])

                {

                    dp[i][j]=dp[i+1][j-1];

                    if(i!=j)path[i][j]=s[i]+path[i+1][j-1]+s[j];

                    else

                        path[i][j]=s[i];

                }

                else

                {

                    if(dp[i+1][j]<dp[i][j-1])

                    {

                        dp[i][j]=dp[i+1][j]+1;

                        path[i][j]=path[i+1][j];

                    }

                    else

                        if(dp[i+1][j]==dp[i][j-1])

                        {               

                            dp[i][j]=dp[i+1][j]+1;

                            path[i][j]=min(path[i+1][j],path[i][j-1]);

                        }

                        else

                        {

                            dp[i][j]=dp[i][j-1]+1;

                            path[i][j]=path[i][j-1]; 

                        }

                }

                cout<<path[0][n-1]<<endl;

    }

    return 0;

}

你可能感兴趣的:(sequence)