[ural1297]Palindrome
求出后缀数组和height数组,然后将这个串反过来写在前面然后枚举中心点并求两边的最长公共前缀即可(一定要加连接符)。

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 int n,m,ans,a[N],b[N],h[N],sum[N],ra[N<<1],sa[N]; 5 char s[N],s1[N]; 6 void change(){ 7 for(int i=0;i<n;i++)a[i]=s[i]; 8 memcpy(ra,a,sizeof(a)); 9 sort(a,a+n); 10 m=unique(a,a+n)-a; 11 for(int i=0;i<n;i++)ra[i]=lower_bound(a,a+m,ra[i])-a+1; 12 } 13 void sort(int k){ 14 memset(sum,0,sizeof(sum)); 15 for(int i=0;i<n;i++)sum[ra[i+k]+1]++; 16 for(int i=1;i<=m;i++)sum[i+1]+=sum[i]; 17 for(int i=0;i<n;i++)b[sum[ra[a[i]+k]]++]=a[i]; 18 } 19 void build(){ 20 for(int i=1;;i<<=1){ 21 for(int j=0;j<n;j++)a[j]=j; 22 sort(i); 23 memcpy(a,b,sizeof(a)); 24 sort(0); 25 m=a[b[0]]=1; 26 for(int j=1;j<n;a[b[j++]]=m) 27 if ((ra[b[j-1]]!=ra[b[j]])||(ra[b[j-1]+i]!=ra[b[j]+i]))m++; 28 memcpy(ra,a,sizeof(a)); 29 if (m==n)break; 30 } 31 for(int i=0;i<n;i++)sa[ra[i]]=i; 32 } 33 void height(){ 34 m=0; 35 for(int i=0;i<n;h[ra[i++]]=m,m-=(m>0)) 36 for(int j=sa[ra[i]-1];(i!=j)&&(s[i+m]==s[j+m]);m++); 37 h[1]=0; 38 } 39 int lcp(int x,int y){ 40 int ans=0x3f3f3f3f; 41 if (ra[x]>ra[y])swap(x,y); 42 for(int i=ra[x]+1;i<=ra[y];i++)ans=min(ans,h[i]); 43 return ans; 44 } 45 void write(int x,int y){ 46 for(int i=x;i<=y;i++)printf("%c",s[i]); 47 } 48 int main(){ 49 scanf("%s",s); 50 n=strlen(s); 51 s[n]='0'; 52 for(int i=1;i<=n;i++)s[i+n]=s[n-i]; 53 n=n*2+1; 54 change(); 55 build(); 56 height(); 57 for(int i=0;i<n/2;i++) 58 ans=max(ans,max(2*lcp(i,n-i-1)-1,2*lcp(i,n-i))); 59 for(int i=0;i<n/2;i++){ 60 if (2*lcp(i,n-i-1)-1==ans){ 61 write(i-ans/2,i+ans/2); 62 return 0; 63 } 64 if (2*lcp(i,n-i)==ans){ 65 write(i-ans/2,i+ans/2-1); 66 return 0; 67 } 68 } 69 }