重复旋律大礼包
http://hihocoder.com/problemset/problem/1407
1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<vector> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define N 100010 10 #define RG register 11 #define inf 0x3f3f3f3f 12 #define Inf 99999999999999999LL 13 using namespace std; 14 typedef long long LL; 15 int l=1,n,r,ans,a[N],b[N],sa[N],num[N],ssa[N],cnta[N],cntb[N],heit[N],order[N]; 16 inline int Abs(RG const int &a){return a>0?a:-a;} 17 inline int Max(RG const int &a,RG const int &b){return a>b?a:b;} 18 inline int Min(RG const int &a,RG const int &b){return a>b?b:a;} 19 inline int gi(){ 20 RG int x=0;RG bool flag=0;RG char c=getchar(); 21 while((c<'0'||c>'9')&&c!='-') c=getchar(); 22 if(c=='-') c=getchar(),flag=1; 23 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 24 return flag?-x:x; 25 } 26 inline void getsa(){ 27 for (RG int i=1;i<=n;++i) ++cnta[num[i]]; 28 for (RG int i=1;i<=1000;++i) cnta[i]+=cnta[i-1]; 29 for (RG int i=n;i;--i) sa[cnta[num[i]]--]=i; 30 order[sa[1]]=1; 31 //cout<<"sdmo"<<endl; 32 if(n>1){ 33 for (RG int i=2;i<=n;++i){ 34 order[sa[i]]=order[sa[i-1]]; 35 if(num[sa[i]]!=num[sa[i-1]]) ++order[sa[i]]; 36 } 37 //cout<<"cdsamoc"<<endl; 38 for (RG int now=1;order[sa[n]]<n;now<<=1){ 39 memset(cnta,0,sizeof(cnta)); 40 memset(cntb,0,sizeof(cntb)); 41 for (RG int i=1;i<=n;++i){ 42 ++cnta[a[i]=order[i]]; 43 ++cntb[b[i]=(i+now<=n)?order[i+now]:0]; 44 } 45 for (RG int i=1;i<=n;++i) cntb[i]+=cntb[i-1]; 46 for (RG int i=n;i;--i) ssa[cntb[b[i]]--]=i; 47 for (RG int i=1;i<=n;++i) cnta[i]+=cnta[i-1]; 48 for (RG int i=n;i;--i) sa[cnta[a[ssa[i]]]--]=ssa[i]; 49 order[sa[1]]=1; 50 for (RG int i=2;i<=n;++i){ 51 order[sa[i]]=order[sa[i-1]]; 52 if(a[sa[i]]!=a[sa[i-1]]||b[sa[i]]!=b[sa[i-1]]) ++order[sa[i]]; 53 } 54 } 55 //cout<<"dsji"<<endl; 56 } 57 for (RG int i=1,j=0;i<=n;++i){ 58 if(j) --j; 59 while(num[i+j]==num[sa[order[i]-1]+j]) ++j; 60 heit[order[i]]=j; 61 } 62 } 63 inline bool check(RG int mid){ 64 RG int maxn,minn=inf; 65 for (RG int i=1;i<=n;++i) 66 if(heit[i]<mid) 67 maxn=minn=sa[i]; 68 else{ 69 maxn=Max(maxn,sa[i]); 70 minn=Min(minn,sa[i]); 71 if(maxn-minn>=mid) return 1; 72 } 73 return 0; 74 } 75 inline void work(){ 76 n=gi();r=n; 77 for (RG int i=1;i<=n;++i) num[i]=gi(); 78 //cout<<"cesj"<<endl; 79 getsa(); 80 //cout<<"feanfila"<<endl; 81 while(l<=r){ 82 RG int mid=(l+r)>>1; 83 if(check(mid)) ans=mid,l=mid+1; 84 else r=mid-1; 85 } 86 printf("%d ",ans); 87 } 88 int main(){ 89 work(); 90 return 0; 91 }