题目来源:http://codeforces.com/problemset/problem/335/B
求最长回文子串(可以不连续)
题目给的长度为5·104
但是只要求最多输出长度为100的回文串
并且母串只有小写字母 所以当母串问2600时必定有长度为一百的回文串
所以只要截取母串的前2600个字符就行
然后n*n 的复杂度DP
f[i][j]=max(f[i][j-1],f[i+1][j]);
if(s[i]==s[j]) f[i][j]=max(f[i][j],f[i+1][j-1]+2);
代码如下:
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
const int maxn=2601;
int dp[maxn][maxn];//dp[i][j]表示区间[i,j]中回文子串的长度
int L[maxn][maxn];
int R[maxn][maxn];
int main()
{
string s;
cin>>s;
int len=min(maxn,(int)s.size());
for(int i=0; i<len; ++i)
dp[i][i]=1;
for(int i=1; i<len; ++i)
for(int j=0; j+i<len; ++j)
{
int k=j+i;
if(dp[j+1][k]>dp[j][k])
{
dp[j][k]=dp[j+1][k];
L[j][k]=j+1;
R[j][k]=k;
}
if(dp[j][k-1]>dp[j][k])
{
dp[j][k]=dp[j][k-1];
L[j][k]=j;
R[j][k]=k-1;
}
if(s[j]==s[k]&&dp[j+1][k-1]+2>dp[j][k])
{
dp[j][k]=dp[j+1][k-1]+2;
L[j][k]=j+1;
R[j][k]=k-1;
}
}
int ans=min(dp[0][len-1],100);
char ch[102]="";
int ls=0, rs=len-1;
int lc=0, rc=ans-1;
while(lc<=rc)
{
if(lc==rc)
{
ch[lc]=s[ls];
break;
}
if(s[ls]==s[rs])
{
ch[lc]=ch[rc]=s[ls];
lc++;
rc--;
ls++;
rs--;
continue;
}
int lx=ls, rx=rs;
ls=L[lx][rx];
rs=R[lx][rx];
}
cout<<ch<<endl;
return 0;
}