ural1297 palindrome
【题意】
求最长回文子串
【分析】
把原字符串翻过来接到后面,中间放一个特殊字符
然后枚举每一个点作为回文串的中心,计算当前位置的后缀和对应的延长位置上的后缀的最长公共前缀
具体的:分类讨论如果i为奇数长度的中心lcp(i,n-i-1),i为偶数长度回文串的中心的一个lcp(i,n-i)
【代码】
#include<cstdio> #include<cstring> #include<iostream> #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; const int maxn = 3000+10; const int maxd = 22; int s[maxn]; int sa[maxn],c[maxn],t[maxn],t2[maxn]; void build_sa(int m,int n) { 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; 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]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++; if(p>=n) break; m=p; } } int rank[maxn],height[maxn]; void getHeight(int n) { int i,j,k=0; for(i=0;i<=n;i++) rank[sa[i]]=i; for(i=0;i<n;i++) { if(k) k--; j=sa[rank[i]-1]; while(s[j+k]==s[i+k]) k++; height[rank[i]]=k; } } int A[maxn][maxd]; void RMQ_init(int n) { for(int i=1;i<=n;i++) A[i-1][0]=height[i]; for(int k=1;(1<<k)<=n;k++) for(int i=0;(i+(1<<k))<=n;i++) A[i][k]=min(A[i][k-1],A[i+(1<<(k-1))][k-1]); } int query(int l,int r) { int k=0; while(1<<(k+1)<=(r-l+1)) k++; return min(A[l][k],A[r-(1<<k)+1][k]); } int lcp(int a,int b) { int l=rank[a],r=rank[b]; if(r<l) swap(l,r); l--,r--; if(r<0) return 0; return query(l+1,r); //l+1 } int n; char expr[maxn]; int main() { freopen("a.in","r",stdin); freopen("a.ans","w",stdout); while(scanf("%s",expr)==1) { int len=strlen(expr),n=2*len+1; for(int i=0;i<len;i++)s[i]=expr[i]; s[len]=1; for(int i=0;i<len;i++)s[i+len+1]=expr[len-1-i]; s[n]=0; build_sa('z'+1,n+1); getHeight(n); RMQ_init(n); int ans=0,front,tmp; for(int i=0;i<n;i++) { tmp=lcp(i,n-i-1); if(2*tmp-1>ans) { ans=2*tmp-1; front=i-tmp+1; } tmp=lcp(i,n-i); if(2*tmp>ans) { ans=2*tmp; front=i-tmp; } } expr[front+ans]='\0'; printf("%s\n",expr+front); } return 0; }