poj1743(字尾陣列)
阿新 • • 發佈:2019-01-05
本題需要對s陣列做一下調整,然後求陣列s中最長不重疊重複子串
#include<cstdio> #include<cstring> const int maxn=20005; int s[maxn],rank[maxn],height[maxn],sa[maxn],wa[maxn],wb[maxn],wv[maxn],ws[maxn],n; int mind[maxn][15],maxd[maxn][15]; void adjust_s(int *s,int &n) { int i=0,minv=200; for(i=0;i<n-1;i++) { s[i]=s[i+1]-s[i]; minv=minv>s[i]?s[i]:minv; } for(i=0;i<n-1;i++) { s[i]-=minv; } n--; /*for(i=0;i<n;i++) printf("%d ",s[i]); printf("\n");*/ } int cmp(int *r,int a,int b,int l) { if(r[a]!=r[b]) return 1; if(a+l>=n && b+l>=n) return 0; if(a+l<n && b+l<n && r[a+l]==r[b+l]) return 0; return 1; } void build_sa(int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=s[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; for(j=1,p=1;p<n;j<<=1,m=p) { p=0; for(i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; t=x;x=y;y=t;p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)==0?p-1:p++; } /*for(i=0;i<n;i++) printf("%d ",sa[i]); printf("\n");*/ } void get_height() { int i,j,k=0; for(i=0;i<n;i++) rank[sa[i]]=i; for(i=0;i<n;i++) { if(k) k--; j=rank[i]-1; if(j==-1) { height[0]=0; continue; } j=sa[j]; while(s[i+k]==s[j+k]) k++; height[rank[i]]=k; } /*for(i=0;i<n;i++) printf("%d ",rank[i]); printf("\n"); for(i=0;i<n;i++) printf("%d ",height[i]); printf("\n");*/ } int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a>b?b:a; } void RMQ_INIT(int *r,int n) { int i,j; for(i=0;i<n;i++) mind[i][0]=maxd[i][0]=r[i]; for(j=1;(1<<j)<=n;j++) { for(i=0;i+(1<<j)-1<n;i++) { mind[i][j]=min(mind[i][j-1], mind[i+(1<<(j-1))][j-1]); maxd[i][j]=max(maxd[i][j-1], maxd[i+(1<<(j-1))][j-1]); } } } int RMQ_QUERY(int l,int r,int flag) { int k=0; while((1<<(k+1))<(r-l+1)) k++; if(flag) return max(maxd[l][k], maxd[r-(1<<k)+1][k]); else return min(mind[l][k], mind[r-(1<<k)+1][k]); } int judge(int k) { int i,j,v1,v2,start=1,end=0; for(i=1;i<n;i++) { if(height[i]>=k) end++; if((height[i]<k || i==n-1) && start<=end) { v1=RMQ_QUERY(start-1,end,0); v2=RMQ_QUERY(start-1,end,1); if(v2-v1>k) return 1; start=i+1;end=i; } if((height[i]<k || i==n-1) && start>end) { start=i+1;end=i; } } return 0; } int main() { int i,j,mid,l,r; while(scanf("%d",&n)!=EOF&&n!=0) { for(i=0;i<n;i++) scanf("%d",&s[i]); if(n<10) { printf("0\n"); continue; } adjust_s(s,n); build_sa(200); get_height(); RMQ_INIT(sa,n); l=0;r=n/2; while(l<=r) { mid=(l+r)/2; if(judge(mid)) l=mid+1; else r=mid-1; } printf("%d\n",l>=5?l:0); } return 0; }