贪心,后缀数组保证正确性
#include<bits/stdc++.h>
#define rep2(i,k,n) for(int i=k;i>=(n);i--)
#define rep(i,k,n) for(int i=k;i<(n);i++)
using namespace std;
const int maxn=100000;
int n;
char read(){char c=getchar();while(c<'A' || c>'Z')c=getchar();return c;}
char s[maxn],s2[maxn];int p1[maxn],p2[maxn],sa[maxn],rank[maxn],c[maxn],sim,h[maxn];
void build_sa(){
int*x=p1;int*y=p2;
rep(i,0,n)c[x[i]=s[i]]++;
rep(i,1,sim)c[i]+=c[i-1];
rep2(i,n-1,0)sa[--c[x[i]]]=i;
for(int h=1;h<=n;h<<=1){int t=0;
rep(i,n-h,n)y[t++]=i;rep(i,0,n)if(sa[i]>=h)y[t++]=sa[i]-h;
rep(i,0,sim)c[i]=0;
rep(i,0,n)c[x[y[i]]]++;
rep(i,1,sim)c[i]+=c[i-1];
rep2(i,n-1,0)sa[--c[x[y[i]]]]=y[i];
swap(x,y);t=0;
x[sa[0]]=0;
rep(i,1,n)x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+h]==y[sa[i-1]+h] ? t : ++t;
t++;if(t>=n)break;
sim=t;
}
}
void geth(){
rep(i,0,n)rank[sa[i]]=i;
int k=0;
rep(i,0,n){if(!rank[i])continue;
if(k)k--;
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k])k++;
h[rank[i]]=k;
}
}
int main(){//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
scanf("%d",&n);int cn=n;
rep(i,0,n)s[i]=s[2*n-i]=read();s[n]=0;n=n<<1|1;sim=233;
build_sa();
geth();
int l=0,r=cn-1,t=0;
while(l<=r){
s2[t++]=rank[l] > rank[n-r-1] ? s[r--] : s[l++];
}
rep(i,0,t){
putchar(s2[i]);if(!((i+1)%80))printf("\n");
}
return 0;
}