求一个串的最长回文子串
把原串的反串加个原串后面,中间加个没有出现过的字符
然后,原串中,下标i在反串中对应的位置为2*l-i
如果求以i为对称轴的回文串,我们求suffix(i)和suffix(2*l-i)的LCP
如果求以i和i+1为对称轴的回文串,我们求suffix(i+1)和suffix(2*l-i)的LCP
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=2010;
char s[maxn];
int sa[maxn],t[maxn],t2[maxn],c[maxn];
int n;
void build_sa(int n, int m)
{
int i,*x=t,*y=t2;
//基数排序
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=s[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
//直接利用sa数组排序第二关键字
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++)
if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=0;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
if(p>=n) break;
m=p;
}
}
//LCP
int ranks[maxn],height[maxn],d[maxn][15];
void getHeight()
{
int i,j,k=0;
for(i=0;i<=n;i++) ranks[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k) k--;
int j=sa[ranks[i]-1];
while(s[i+k]==s[j+k]) k++;
height[ranks[i]]=k;
}
}
void RMQ()
{
for(int i=1;i<n;i++) d[i][0]=height[i];
for(int j=1;(1<<j)<n;j++)
for(int i=1;i+(1<<j)-1<n;i++)
d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int LCP(int L,int R)
{
int a=ranks[L],b=ranks[R];
if(a>b)
swap(a,b);
a++;
int t=(int)(log(double(b-a+1))/log(2.00));
return min(d[a][t],d[b-(1<<t)+1][t]);
}
void solve()
{
int res=0,id=0;
int l=n/2;
for(int i=0;i<l;i++)
{
int t=LCP(i,n-i-1);
if(2*t-1>res)
{
res=2*t-1;
id=i;
}
if(s[i]==s[i+1])
{
t=LCP(i+1,n-i-1);
if(2*t>res)
{
res=2*t;
id=i;
}
}
}
cout<<res<<endl;
id=id-(res-1)/2;
for(int j=0;j<res;j++)
{
cout<<s[id+j];
}
cout<<endl;
}
int main()
{
cin>>s;
n=strlen(s);
s[n]=24;
for(int i=0;i<n;i++)
{
s[n+i+1]=s[n-i-1];
}
n=2*n+1;
s[n+1]='\0';
build_sa(n+1,200);
getHeight();
RMQ();
solve();
return 0;
}