题意:输入一个串,通过环形变换使它最小。(n<=300000)
裸的后缀排序啊!
(卡常把命都卡掉了)
后缀数组记得开大啊
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int x[1200005],y[1200005],u[1200005],v[1200005],r[1200005],o[1200005],n,m=700000; 5 int str[600005],buf[600005]; 6 7 int main(){ 8 scanf("%d",&n); 9 for(int i=1;i<=n;i++) scanf("%d",&str[i]),buf[i]=str[i]; 10 sort(buf+1,buf+n+1); 11 for(int i=1;i<=n;i++) str[i]=lower_bound(buf+1,buf+n+1,str[i])-buf; 12 for(int i=1;i<=n;i++) str[i+n]=str[i]; 13 14 n*=2; 15 16 for(register int i=1;i<=n;i++) u[str[i]]++; 17 for(register int i=1;i<=m;i++) u[i]+=u[i-1]; 18 for(register int i=n;i>=1;i--) x[u[str[i]]--]=i; 19 r[x[1]]=1; 20 for(int i=2;i<=n;i++) r[x[i]]=r[x[i-1]]+(str[x[i]]!=str[x[i-1]]); 21 22 for(int l=1;r[x[n]]<n;l<<=1) { 23 memset(u,0,sizeof u); 24 memset(v,0,sizeof v); 25 memcpy(o,r,sizeof r); 26 for(register int i=1;i<=n;i++) u[r[i]]++, v[r[i+l]]++; 27 for(register int i=1;i<=n;i++) u[i]+=u[i-1], v[i]+=v[i-1]; 28 for(register int i=n;i>=1;i--) y[v[r[i+l]]--]=i; 29 for(register int i=n;i>=1;i--) x[u[r[y[i]]]--]=y[i]; 30 r[x[1]]=1; 31 for(register int i=2;i<=n;i++) 32 r[x[i]]=r[x[i-1]]+((o[x[i]]!=o[x[i-1]])||(o[x[i]+l]!=(o[x[i-1]+l]))); 33 } 34 35 for(int i=1;i<=n;i++) 36 if(x[i]<=n/2) { 37 for(register int j=1;j<=n/2;j++) printf("%d ",buf[str[x[i]+j-1]]); 38 return 0; 39 } 40 }
原文地址:https://www.cnblogs.com/mollnn/p/8449690.html
时间: 2024-10-03 23:32:09