2013-03-10 20:09:16Morris

[UVA][最小迴文][LCS] 11404 - Palindromic Subsequence


  Palindromic Subsequence 

A Subsequence is a sequence obtained by deleting zero or more characters in a string. A Palindrome is a string which when read from left to right, reads same as when read from right to left. Given a string, find the longest palindromic subsequence. If there are many answers to it, print the one that comes lexicographically earliest.


Constraints

  • Maximum length of string is 1000.
  • Each string has characters `a' to `z' only.

Input 

Input consists of several strings, each in a separate line. Input is terminated by EOF.

Output 

For each line in the input, print the output in a single line.

Sample Input 

aabbaabb
computer
abzla
samhita

Sample Output 

aabbaa
c
aba
aha




先說說找最長迴文,字串與反轉的字串做一次 LCS,即可以得到最長迴文的長度。

做一次 LCS 很簡單,要找出字典順序最小的卻不容易。
但這題並不是在 LCS 中找字典順序最小的,因為字典順序最小不見得是迴文

kfclbckibbibjccbej


這個字串最長迴文是
bcibbicb
但字典順序最小的 LCS 卻是 bcibbibc

因此做到一半就行了。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
short dp[1005][1005];
char used[1005][1005];
int main() {
    char s[1005], rs[1005];
    int n, i, j;
    while(gets(s)) {
        n = strlen(s);
        for(i = 0; i < n; i++)
            rs[i] = s[n-i-1];
        rs[n] = '\0';
        for(i = 1; i <= n; i++) {
            for(j = 1; j <= n; j++) {
                if(s[i-1] == rs[j-1])
                    dp[i][j] = dp[i-1][j-1]+1;
                else
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                used[i][j] = 0;
            }
        }
        int len = dp[n][n], x, y;
        queue<int> X, Y, rX, rY;
        char ans[1005];
        for(i = len/2; i >= 0; i--) {
            char output = 127;
            if(i == len/2) {
                X.push(n), Y.push(n);
                used[n][n] = 1;
                if(s[n-1] == rs[n-1])
                    output = s[n-1];
            }
            while(!X.empty()) { // equal
                x = X.front(), X.pop();
                y = Y.front(), Y.pop();
                rX.push(x), rY.push(y);
                if(s[x-1] == rs[y-1])
                    output = min(output, s[x-1]);
                if(dp[x-1][y] == dp[x][y] && used[x-1][y] == 0)
                    used[x-1][y] = 1, X.push(x-1), Y.push(y);
                if(dp[x][y-1] == dp[x][y] && used[x][y-1] == 0)
                    used[x][y-1] = 1, X.push(x), Y.push(y-1);
            }
            ans[i] = output;
            putchar(output);
            while(!rX.empty()) {
                x = rX.front(), rX.pop();
                y = rY.front(), rY.pop();
                if(s[x-1] == rs[y-1] && s[x-1] == output) {
                    X.push(x-1), Y.push(y-1);
                    used[x-1][y-1] = 1;
                }
            }
        }
        for(i = 1+(len%2 == 0); i <= len/2; i++)
            putchar(ans[i]);
        puts("");
    }
    return 0;
}