UVA 11404 - Palindromic Subsequence LCS
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2399
题目大意:
给定一个由小写字母组成的字符串,删除其中0个或多个字符,使得剩下的字母(顺序不变)组成一个尽量长的回文串。如果有多解,输出字典序最小的解。
思路:
参考别人思路的。。
学到的有:
把一个字符串逆序后和原字符串进最长公共子序列,可以计算出它的最长回文串长度。
这题还要求输出字典序最小的解。
回忆一下LCS过程,如果A[I]==B[j]那么dp[i][j]=dp[i-1][j-1]+1,否则dp[i][j]=max(dp[i-1,j],dp[i][j-1])
这题则需要在dp过程中记录当前串。至于字典序的判断,如果A[I]!=B[j]并且dp[i-1,j]==dp[i][j-1]时,判断(i-1,j)和(i,j-1)记录的字符串哪个字典序小即可。
需要注意的是LCS不一定为回文串。
例如:
kfclbckibbibjccbej
jebccjbibbikcblcfk
bcibbibc是他们的LCS,但是却不是回文串。
但我们可以根据前半段推出后面的。
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN=1024; char s[MAXN],a[MAXN]; int dp[MAXN][MAXN]; string ans[MAXN][MAXN]; int main() { while(~scanf("%s",s+1)) { int L=strlen(s+1); for(int i=0;i<L;i++) { dp[0][i]=0; ans[0][i]=""; } for(int i=L,j=1;i>=1;i--,j++) a[j]=s[i]; //这样,问题转化为求s和a的LCS for(int i=1;i<=L;i++) { for(int j=1;j<=L;j++) { if(a[j]==s[i]) { dp[i][j]=dp[i-1][j-1]+1; ans[i][j]=ans[i-1][j-1]+s[i]; } else { if(dp[i-1][j] > dp[i][j-1]) { dp[i][j]=dp[i-1][j]; ans[i][j]=ans[i-1][j]; } else if(dp[i-1][j] < dp[i][j-1]) { dp[i][j]=dp[i][j-1]; ans[i][j]=ans[i][j-1]; } else { dp[i][j]=dp[i][j-1]; ans[i][j]=min(ans[i-1][j],ans[i][j-1]); } } } } string &res=ans[L][L]; int len=res.size(); len>>=1; // cout<<res<<endl; for(int i=0;i<len;i++) cout<<res[i]; int i; if(res.size() &1) i=len; else i=len-1; for(;i>=0;i--) cout<<res[i]; cout<<endl; } }
新 blog : www.hrwhisper.me