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);
}

posted on 2011-03-13 15:12  宇宙吾心  阅读(571)  评论(0)    收藏  举报

导航