UVA - 11404 Palindromic Subsequence (最长回文子序列)

题意:给定一个由小写字母组成的字符串,删除其中的0个或者多个字符,使得剩下的字母(顺序不变)组成一个尽量长的回文串,如果有多解,输出字典序最小的解

思路:最长回文子序列的求法是:将一个串置反,求新旧串的最长公共子序列,因为还要按字典序所以开个结构体,注意我们求出的只是回文串的一半

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1010;

struct node{
    int len;
    string str;
    bool operator <(const node &a)const
    {
        return (len==a.len&&str>a.str)||(len<a.len);
    }
};

char str1[MAXN];
char str2[MAXN];
char res[MAXN];
node dp[MAXN][MAXN],ans;

void Lcs(int n){
    for (int i = 0; i <= n; i++){
        dp[i][0].len = dp[0][i].len = 0;
        dp[i][0].str.clear();
        dp[0][i].str.clear();
    }

    ans.len = 0;
    ans.str.clear();
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            if (str1[i-1] == str2[j-1]){
                dp[i][j].len = dp[i-1][j-1].len + 1;
                dp[i][j].str = dp[i-1][j-1].str+str1[i-1];
            }
            else if (dp[i-1][j] < dp[i][j-1])
                dp[i][j] = dp[i][j-1];
            else dp[i][j] = dp[i-1][j];
            if (ans < dp[i][j])
                ans = dp[i][j];
        }
    }
    int len = ans.len/2,m=0;
    for (int i = 0; i < len; i++)
        res[m++] = ans.str[i];
    if (ans.len & 1)
        res[m++] = ans.str[len];
    for (int i = len-1; i >= 0; i--)
        res[m++] = ans.str[i];
    res[m] = '\0';
}

int main(){
    while (scanf("%s",str1) != EOF){
        int n = strlen(str1);
        for (int i = 0; i < n; i++)
            str2[i] = str1[n-1-i];
        Lcs(n);
        printf("%s\n",res);
    }
    return 0;
}



你可能感兴趣的:(UVA - 11404 Palindromic Subsequence (最长回文子序列))