算法:uva 11404 Palindromic Subsequence(LCS回文串,最小字典序)

题目大意

给一个字符串,输出它的最长回文串,如果有多个结果,输出字典序最小的。

思 路

我们都知道把一个字符串逆序后和原字符串进最长公共子序列,可以计算出它的最长回文串长度。

但是这题不仅要输出回文串,而且还要求是字典序最小的,所以挺难搞的。

设str1是正序字符串, str2是逆序后的字符串

f[i][j].len 表示str1的前i位,str2的前j位,最长公共子串的长度

f[i] [j].str 表示str1的前i位,str2的前j位,最长公共子串的最小字典序的字符串

状态转移和正常的LCS差 不多,只不过增加了记录字典序最小的字符串

但是最终的f[i][j].str却并不一定是答案,因为计算出来 的最长公共子序列不一定就是回文串

例如:

kfclbckibbibjccbej

jebccjbibbikcblcfk

bcibbibc 是他们的LCS,但是却不是回文串

但是它的前len/2个一定是回文串的前半部分

知道了前len/2,就 可以直接构造出回文串的后半部分了

要注意长度的奇偶性问题

代码

/**==========================================
* This is a solution for ACM/ICPC problem
*
* @source:uva-11404 Palindromic Subsequence
* @type: LCS最小字典序回文串
* @author: shuangde
* @blog: blog.csdn.net/shuangde800
* @email: zengshuangde@gmail.com
*===========================================*/

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;

typedef long long int64;
const int INF = 0x3f3f3f3f;

const int MAXN = 1010;
char str1[MAXN], str2[MAXN];
int n, len;

struct Node{
int len;
string str;
}f[MAXN][MAXN];

int main(){

Node a, b;

while(gets(str1+1)){

// reverse
len = strlen(str1+1);
for(int i=1; i<=len; ++i)
str2[i] = str1[len+1-i];

// init
for(int i=0; i<=len; ++i)
f[0][i].len = 0, f[0][i].str = "";

// LCS
for(int i = 1; i <= len; ++i) {
for(int j = 1; j <= len; ++j) {
if (str1[i] == str2[j]) {
f[i][j].len = f[i-1][j-1].len + 1;
f[i][j].str = f[i-1][j-1].str + str1[i];

} else {
if(f[i-1][j].len > f[i][j-1].len) {
f[i][j].len = f[i-1][j].len;
f[i][j].str = f[i-1][j].str;

} else if (f[i][j-1].len > f[i-1][j].len) {
f[i][j].len = f[i][j-1].len;
f[i][j].str = f[i][j-1].str;

} else {
f[i][j].len = f[i-1][j].len;
f[i][j].str = min(f[i-1][j].str, f[i][j-1].str);
}
}
}
}

int maxx = f[len][len].len;
string ans = f[len][len].str;

// output
// www.bianceng.cn
if(maxx & 1) {
for(int i = 0; i < maxx/2; ++i)
cout << ans[i];
for(int i = maxx/2; i >= 0; --i)
cout << ans[i];
putchar('\n');

} else {
for(int i = 0; i < maxx/2; ++i)
cout << ans[i];
for(int i = maxx/2-1; i >= 0; --i)
cout << ans[i];
putchar('\n');
}
}
return 0;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索字符串
, include
, 空字符串
, 回文
, 字典
, c 回文字符串
, 回文数问题java算法
, 最长公共子串
, 公共字符串长度
, 最大公共子串
, 最长
, 回文字符串
, 公共子串
最小
palindromic、palindromic number、palindromic string、palindromic sequence、subsequence,以便于您获取更多的相关知识。

时间: 2025-01-02 13:58:30

算法:uva 11404 Palindromic Subsequence(LCS回文串,最小字典序)的相关文章

leetcode 5 Longest Palindromic Substring--最长回文字符串

问题描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的.比如"a" , "aaabbaaa" 之前

[百度]2014百度校园招聘之最长回文串

[题目] 给你一个字符串,找出该字符串中对称的子字符串的最大长度.即求最大回文串. [思路1]暴力法 即不使用技巧,穷举所有可能.时间复杂度为O(n^3)(时间上最长,不推荐使用),空间复杂度为O(1). 本思路是从最大长度的字串开始,而不是从最小开始.假如说给定的字符串为len,先遍历长度为len的字串是否为回文串,如果是停止, 如果不是遍历长度为len-1的字串是否是回文串,一次类推. #include <iostream> using namespace std; //是否是回文串 bo

[经典面试题]回文串专题

[小米]2015小米校招之回文数判断 [百度]2014百度校园招聘之最长回文串 [网易]字符串回文分割 [创新工场]2014创新工场校园招聘之回文串修复 [算法]Manacher算法之最大回文子串 [LeetCode]9.Palindrome Number [LeetCode]125.Valid Palindrome [LeetCode]131.Palindrome Partitioning [LeetCode]132.Palindrome Partitioning II

关于c语言回文串的问题

问题描述 关于c语言回文串的问题 问题描述 回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的.小龙龙认为回文串才是完美的.现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串. 交换的定义是:交换两个相邻的字符 例如mamad 第一次交换 ad : mamda 第二次交换 md : madma 第三次交换 ma : madam (回文!完美!) 输入格式 第一行是一个整数N,表示接下来的字符串的长度(N <= 8000) 第二行是一个字符串,长度为N.

Manacher&#039;s Algorithm 求解字符串的最长回文串

Manacher算法:O(n)求字符串的最长回文串 1:算法可以在O(n)的时间内求出以每一个字符为中心的最长回文串 2:算法把奇数回文串和偶数回文串统一起来考虑 3:算法大致过程是这样.先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过.一般可以用'#'分隔.这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组rad记录以每个字符为中心的最长回文串的信息.rad[i]记录的是以字符str[i]为中心的

Java实现查找当前字符串最大回文串代码分享_java

先看代码 public class MaxHuiWen { public static void main(String[] args) { // TODO Auto-generated method stub String s = "abb"; MaxHuiWen(s); } //1.输出回文串 public static void MaxHuiWen(String s){ //存储字符串的长度 int length = s.length(); //存储最长的回文串 String M

代码审查-最大回文串问题,拜托各位了

问题描述 最大回文串问题,拜托各位了 我找很长时间了,就是找不到错误(可以编译,输出不对),拜托各位看一下,新人,没有悬赏分,感谢各位的回答 #include<iostream> #include<string.h> #include<cctype> using namespace std; int main() { char a[101], b[101]; int c[101]; while (cin.getline(a, 101)) { int i,d, k, x,

NYOJ 1023 还是回文(DP,花最少费用形成回文串)

/* 题意:给出一串字符(全部是小写字母),添加或删除一个字符,都会产生一定的花费. 那么,将字符串变成回文串的最小花费是多少呢? 思路:如果一个字符串增加一个字符 x可以形成一个回文串,那么从这个字符串中删除这个字符 x 同样也能形成回文串! 所以我们只记录删除,和增加这个字符 x 的最小的费用就好了!->转变成添加多少个字符形成回文串费用最少! str[i]!=str[k] dp[i][j]=min(dp[i][j-1]+cost[str[k]-'a'], dp[i+1][j-1]+cost

HDOJ/HDU 2163 Palindromes(判断回文串~)

Problem Description Write a program to determine whether a word is a palindrome. A palindrome is a sequence of characters that is identical to the string when the characters are placed in reverse order. For example, the following strings are palindro