UVA 11404

来源:互联网 发布:nginx redis模块 编辑:程序博客网 时间:2024/06/05 00:52

ASubsequence is a sequence obtained by deleting zero or more characters in astring. A Palindrome is a string which when read from left to right, reads sameas when read from right to left. Given a string, find the longest palindromicsubsequence. If there are many answers to it, print the one that comes lexicographicallyearliest.

Constraints

• Maximum length of string is 1000.

• Each string has characters `a' to `z' only.

Input

Inputconsists of several strings, each in a separate line. Input is terminated byEOF.

Output

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

Sample Input

aabbaabb

computer

abzla

samhita

Sample Output

aabbaa

c

aba

aha

 

题目大意:题意是说找一个给定字符串的最大回文子序列,但这个子序列可以不是连续的,对于多种同样长度的回文子串,取字典序最小的。

根据字符串S0的长度可以采用LCS算法,找出字符串S0和其逆字符串S1的最长公共子序列,同时加一个判断就是对于相同长度的公共子串选取字典序最小的。但是还有一种特殊情况,由于LCS过程中是按照字典序排列的,本题要找的是最大回文子串,LCS并不一定能找到回文序列,借用别的例子:

kfclbckibbibjccbej 

jebccjbibbikcblcfk

按字典序LCS得到为bcibbibc,并不是回文串,但是可以得到其与最长回文子串的长度应该相等,并且前一半与回文子串相同,因此可以根据前一半回文串得出后一半(主要串长度的奇偶性)。LCS做法代码如下:

 

#include<bits/stdc++.h>using namespace std;string dp[1005][1005];string s0;string lcs(){string s1(s0.rbegin(),s0.rend());//逆串int i,j,len;len=s0.length();for(i=0; i<1005; i++){dp[0][i]="";dp[i][0]="";}for(i=1; i<=len; i++){for(j=1; j<=len; j++){if(s0[i-1]==s1[j-1]){dp[i][j]=dp[i-1][j-1]+s0[i-1];}else{if(dp[i-1][j].length()==dp[i][j-1].length())//字典序{dp[i][j]=min(dp[i-1][j],dp[i][j-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];}}}}}return dp[len][len];}int main(){int i,len;string ans;while(cin>>s0){ans=lcs();len=ans.length();for(i = 0; i < len/2; i++)//输出  注意奇偶cout << ans[i];if(len & 1){for(i = len/2; i >= 0; i--)cout << ans[i];}else{for(i =len/2-1; i >= 0; i--)cout << ans[i];}cout<<endl;}return 0;}

练习赛时候做做到题不知道怎么想的,觉得LCS算法不行,于是想了个dp的算法,用book[i][j]表示从S[i]到S[j]的最长回文子串的一半,状态转移方程式book[i][j]=max(book[i+1][j],s[i]+book[i+1][k]),k为从j开始向前查找得到的第一个与S[i]相等的字符的位置,但这样做要判断回文串的长度是奇数还是偶数,还要判断字典序,就比较麻烦,不过不会出现LCS的那种奇葩的情况。这个做法代码如下:

 

#include<bits/stdc++.h>using namespace std;struct str{string s;bool flag;//判断回文串长度是奇数还是偶数};str s;str book[1005][1005];int l;str dp(int p,int q){if(book[p][q].s!=""){return book[p][q];}int i,j,k;str s0,s1,kong,tmp;kong.flag=0;kong.s="";s0.s+=s.s[p];if(p-q==1){kong.flag=0;return kong;}if(p-q==2){kong.flag=1;return kong;}for(i=q;i>=p;i--){if(s.s[i]==s.s[p]){tmp=dp(p+1,i-1);s0.s+=tmp.s;s0.flag=tmp.flag;s1=dp(p+1,q);if(s0.s.length()<s1.s.length()){book[p][q] = s1;return s1;}else{if(s0.s.length()>s1.s.length()){if(p==i)s0.flag=1;book[p][q] = s0;return s0;}else{if(s0.flag==1&&s1.flag==0){book[p][q] = s1;return s1;}if(s0.flag==0&&s1.flag==1){if(p==i)s0.flag=1;book[p][q] = s0;return s0;}if(s0.s>s1.s){book[p][q] = s1;return s1;}else{if(p==i)s0.flag=1;book[p][q] = s0;return s0;}}}}}}int main(){str s0;s0.flag=0;int i,j;while(cin>>s.s){l=s.s.length();for(i=0;i<l;i++){for(j=i;j<l;j++){book[i][j].s="";book[i][j].flag=0;}}dp(0,l-1);s0=book[0][l-1];cout<<s0.s;if(s0.flag==1){i=s0.s.length()-2;}else{i=s0.s.length()-1;}for(;i>=0;i--){cout<<s0.s[i];}cout<<endl;}return 0;}

原创粉丝点击