题意很简单:求最长为20000的数组里,重复次数至少为K次的最长子串;
思路: 后缀树组 + 二分 ,因为数组里的每个元素的最大值为10^6 ,就后缀数组的时候要用快排不用基数排序
http://poj.org/problem?id=3261
#include <iostream> #include <algorithm> #include <cstdio> using namespace std; const int maxn=20010; int r[maxn],wa[maxn],wb[maxn],s[maxn],v[maxn],N,K,sa[maxn]; int cmp1(int a,int b) { if(r[a]==r[b]) return a < b; return r[a] < r[b]; } int cmp2(int a,int b) { if(v[a]==v[b]) return a < b; return v[a] < v[b]; } int cmp(int *p ,int x, int y, int l) { return p[x] == p[y] && p[x + l] == p[y + l]; } void da(int n,int m) { int i,j,*x=wa,*y=wb,*t,p; for(i=0;i<n;i++) s[i]=i,x[i]=r[i]; sort(s,s+n,cmp1); for(i=0;i<n;i++) sa[i]=s[i]; for(p=1,j=1;p<n;j*=2,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(int i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) v[i]=x[y[i]]; for(i=0;i<n;i++) s[i]=i; sort(s,s+n,cmp2); for(i = 0; i < n; i++) sa[i] = y[s[i]]; for(t=x,x=y,y=t,i=1,p=1,x[sa[0]] = -1;i<n;i++) x[sa[i]]=cmp(y, sa[i - 1], sa[i], j) ? p - 1: p ++; } } int rank[maxn],height[maxn]; void cal_height(int n) { int i,j,k; for(i=0;i<=n;i++) rank[sa[i]]=i; for(i=0,k=0;i<n;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); } void solve() { da(N+1,1001000); cal_height(N); // for(int i=0;i<=N;i++) cout<<height[i]<<" "; // cout<<endl; int l=1,r=N,mid,ans=1; while(l<=r) { mid=(l+r)>>1; bool ok=0; for(int i=1,j=1;i<=N;i++) if(height[i]<mid) j=i; else if(i-j+1>=K) { ok=1;break; } if(ok) { ans=mid; l=mid+1; } else r=mid-1; } printf("%d\n",ans); } int main() { while(scanf("%d%d",&N,&K)==2) { for(int i=0;i<N;i++) scanf("%d",r+i); r[N]=-1; if(K==1) printf("%d\n",N); else solve(); } return 0; }