题目大意
给定一个字符串,要求你删除尽量少的字符,使得原字符串变为最长回文串,并把回文串输出,如果答案有多种,则输出字典序最小的
题解
有两种解法,第一种是把字符串逆序,然后求两个字符串的LCS,并记录LCS,长度就等于最长回文串的长度,不过求出来的LCS不一定是回文串,例如下面这个例子
s = 1 5 2 4 3 3 2 4 5 1 reverse(s) = 1 5 4 2 3 3 4 2 5 1 LCS = 1 5 2 3 3 4 5 1
所以我们只需要LCS的前半段即可
代码:
#include <cstdio> #include <algorithm> #include <string> #include <iostream> #include <utility> using namespace std; #define MAXN 1005 string a,b; pair<int,string>dp[MAXN][MAXN]; int main() { while(cin>>a) { int len=a.length(); b=a; reverse(b.begin(),b.end()); for(int i=0;i<len;i++) { dp[0][i].first=0,dp[0][i].second=""; dp[i][0].first=0,dp[i][0].second=""; } for(int i=0;i<len;i++) for (int j=0;j<len;j++) if(a[i]==b[j]) { dp[i+1][j+1].first=dp[i][j].first+1; dp[i+1][j+1].second=dp[i][j].second+a[i]; } else { if(dp[i+1][j].first>dp[i][j+1].first) { dp[i+1][j+1].first=dp[i+1][j].first; dp[i+1][j+1].second=dp[i+1][j].second; } else if(dp[i+1][j].first==dp[i][j+1].first) { dp[i+1][j+1].first=dp[i][j+1].first; dp[i+1][j+1].second=min(dp[i][j+1].second,dp[i+1][j].second); } else { dp[i+1][j+1].first=dp[i][j+1].first; dp[i+1][j+1].second=dp[i][j+1].second; } } int lens=dp[len][len].first; string s=dp[len][len].second; if(lens&1) { int t=lens/2; for(int i=0;i<=t;i++) cout<<s[i]; for(int i=t-1;i>=0;i--) cout<<s[i]; cout<<endl; } else { int t=lens/2; for(int i=0;i<t;i++) cout<<s[i]; for(int i=t-1;i>=0;i--) cout<<s[i]; cout<<endl; } } return 0; }
第二种方法和POJ1159一样,不过是多了个路径而已
代码:
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #include <string> using namespace std; #define MAXN 1005 string s; int dp[MAXN][MAXN]; string path[MAXN][MAXN]; int main() { int n; while(cin>>s) { memset(dp,0,sizeof(dp)); int n=s.length(); for(int i=n-1; i>=0; i--) for(int j=i; j<n; j++) if(s[i]==s[j]) { dp[i][j]=dp[i+1][j-1]; if(i!=j)path[i][j]=s[i]+path[i+1][j-1]+s[j]; else path[i][j]=s[i]; } else { if(dp[i+1][j]<dp[i][j-1]) { dp[i][j]=dp[i+1][j]+1; path[i][j]=path[i+1][j]; } else if(dp[i+1][j]==dp[i][j-1]) { dp[i][j]=dp[i+1][j]+1; path[i][j]=min(path[i+1][j],path[i][j-1]); } else { dp[i][j]=dp[i][j-1]+1; path[i][j]=path[i][j-1]; } } cout<<path[0][n-1]<<endl; } return 0; }