poj 3261
后缀数组,height的二分。
#include<iostream>
#include<fstream>
using namespace std;
#define N 20011
int sa[N],sa1[N],rank[N],rank1[N],c[N],h[N];
int m[N];
int n,pow,count;
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);
}
int cmp1(const void *a,const void *b){
return m[*((int *)a)]-m[*((int *)b)];
}
void creat(){
int i,j,k;
for(i=0;i<n;i++)
sa[i]=i;
qsort(sa,n,sizeof(int),cmp1);
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;
int sum;
for(i=1;i<n;i++)
{
if(h[i]>=len)
{
sum++;
if(sum==count-1)
return 1;
}
else
{
sum=0;
}
}
return(0);
}
int value;
int main(){
int i,j,k,mid;
// ifstream cin("in.txt");
cin>>n>>count;
for(i=1;i<=n;i++)
{
//cin>>m[i-1];
scanf("%d",&m[i-1]);
}
m[n++]=-1;
creat();
height();
i=0;j=n;
while(i<=j)
{
mid=(i+j)/2;
if(judge(mid)) i=mid+1;
else
j=mid-1;
}
cout<<j<<endl;
return(0);
}
浙公网安备 33010602011771号