题意很简单:求最长为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;
}