1. 程式人生 > >洛谷1368 工藝 - 後綴數組

洛谷1368 工藝 - 後綴數組

reg sin name += pan 後綴數組 std pri mem

題意:輸入一個串,通過環形變換使它最小。(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 }

洛谷1368 工藝 - 後綴數組