问题可以转化成LCS输出最小字典序。
用了一种很笨的办法,直接保存dp过程中的每个公共字符串,这样在两个字符不等时且dp【i-1】【j】==dp【i】【j-1】时来比较两个公共字符串的字典序来确定i,j位置的字符串。这样输出也不用倒推回去了,但是空间复杂度比较高。另外有一个问题时此题要求输出回文,这样得到的结果可以不是回文,所以取前半部分然后逆置出后半部分即是答案。
用了1.2S
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 1005
using namespace std;
int dp[MAXN][MAXN];
string path[MAXN][MAXN];
string str1,str2;
int main()
{
ios::sync_with_stdio(false);
while(cin>>str1)
{
str2.clear();
int l=str1.size();
for(int i=l-1; i>=0; --i)
str2+=str1[i];
str1='0'+str1;
str2='0'+str2;
memset(dp,0,sizeof(dp));
for(int i=1; i<=l; ++i)
for(int j=1; j<=l; ++j)
if(str1[i]==str2[j])
{
dp[i][j]=dp[i-1][j-1]+1;
path[i][j]=path[i-1][j-1]+str1[i];
}
else
{
if(dp[i-1][j]==dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
path[i][j]=min(path[i-1][j],path[i][j-1]);
}
else
{
if(dp[i-1][j]>dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
path[i][j]=path[i-1][j];
}
else
{
dp[i][j]=dp[i][j-1];
path[i][j]=path[i][j-1];
}
}
}
string ans;
for(int i=0; i<=(dp[l][l]-1)/2; ++i)
ans+=path[l][l][i];
int st;
if(dp[l][l]%2==0) st=ans.size()-1;
else st=ans.size()-2;
for(int i=st; i>=0; --i)
ans+=ans[i];
cout<<ans<<endl;
}
return 0;
}
用滚动数组优化之后时间变成了0.8S
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 1005
using namespace std;
int dp[3][MAXN];
string path[3][MAXN];
string str1,str2;
int main()
{
ios::sync_with_stdio(false);
while(cin>>str1)
{
str2.clear();
int l=str1.size();
for(int i=l-1; i>=0; --i)
str2+=str1[i];
str1='0'+str1;
str2='0'+str2;
memset(dp,0,sizeof(dp));
for(int i=0; i<=l; ++i)
{
path[0][i].clear();
path[1][i].clear();
}
for(int i=1; i<=l; ++i)
for(int j=1; j<=l; ++j)
if(str1[i]==str2[j])
{
dp[i&1][j]=dp[(i+1)&1][j-1]+1;
path[i&1][j]=path[(i+1)&1][j-1]+str1[i];
}
else
{
if(dp[(i+1)&1][j]==dp[i&1][j-1])
{
dp[i&1][j]=dp[(i+1)&1][j];
path[i&1][j]=min(path[(i+1)&1][j],path[i&1][j-1]);
}
else
{
if(dp[(i+1)&1][j]>dp[i&1][j-1])
{
dp[i&1][j]=dp[(i+1)&1][j];
path[i&1][j]=path[(i+1)&1][j];
}
else
{
dp[i&1][j]=dp[i&1][j-1];
path[i&1][j]=path[i&1][j-1];
}
}
}
string ans;
for(int i=0; i<=(dp[l&1][l]-1)/2; ++i)
ans+=path[l&1][l][i];
int st;
if(dp[l&1][l]%2==0) st=ans.size()-1;
else st=ans.size()-2;
for(int i=st; i>=0; --i)
ans+=ans[i];
cout<<ans<<endl;
}
return 0;
}