poj 1743
后缀数组,经典,height数组的深入理解,想象一下山的形状就明白了。
代码:
#include<iostream> #include<fstream> using namespace std; #define N 20003 int sa[N],sa1[N],rank[N],rank1[N],c[N],h[N],m[N]; int n,pow; int cmp(const void *a,const void *b){ int x=*(int*)a; int y=*(int*)b; if(rank[x]!=rank[y]) return(1); else if(rank[x+pow]!=rank[y+pow]) return(1); else return(0); } void creat(){ int i,j,k; for(i=0;i<500;i++) c[i]=0; for(i=0;i<n;i++) c[m[i]]++; for(i=1;i<500;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[m[i]]]=i; for(i=0,j=0;i<n;i++) { if(i>0&&m[sa[i]]!=m[sa[i-1]]) j++; rank[sa[i]]=j; } for(pow=1;pow<n;pow*=2) { for(i=0;i<n;i++) c[i]=0; for(i=0;i<n;i++) if(sa[i]+pow<n) c[rank[sa[i]+pow]]++; else c[rank[sa[i]]]++; for(i=1;i<n;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) if(sa[i]+pow<n) sa1[--c[rank[sa[i]+pow]]]=sa[i]; else sa1[--c[rank[sa[i]]]]=sa[i]; for(i=0;i<n;i++) c[i]=0; for(i=0;i<n;i++) c[rank[sa1[i]]]++; for(i=1;i<n;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[rank[sa1[i]]]]=sa1[i]; for(i=0,j=0;i<n;i++) { if(i>0&&cmp(&sa[i],&sa[i-1])!=0) j++; rank1[sa[i]]=j; } for(i=0;i<n;i++) rank[i]=rank1[i]; } } void height(){ int i,j,k=0; for(i=0;i<n;i++) { if(rank[i]==0) h[rank[i]]=k=0; else { if(k>0) k--; j=sa[rank[i]-1]; for(;m[i+k]==m[j+k];k++); h[rank[i]]=k; } } } int judge(int len){ int i,mi,ma; mi=sa[0];ma=sa[0]; for(i=1;i<n;i++) { if(h[i]>=len) { if(sa[i]>ma) ma=sa[i]; if(sa[i]<mi) mi=sa[i]; if(ma-mi>=len) return(1); } else { mi=sa[i];ma=sa[i]; } } return(0); } int main(){ int i,j,k,mid; //ifstream cin("in.txt"); while(1){ scanf("%d",&n); if(n==0) return(0); scanf("%d",&j); n--; for(i=0;i<n;i++) { scanf("%d",&m[i]); k=m[i]; m[i]=m[i]-j+100; j=k; } m[n]=0; n++; creat(); height(); i=0;j=n; while(i<=j) { mid=(i+j)/2; if(judge(mid)) i=mid+1; else j=mid-1; } if(j>=4) cout<<j+1<<endl; else cout<<0<<endl; } return(0); }