P2852 [USACO06DEC]牛奶模式Milk Patterns

link\

这是一道后缀匹配的模板题

我们只需要将height算出来

然后二分一下答案就可以了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1010000;
int data[maxn];
int rank[maxn];
int tot[maxn];
int sa[maxn];
int pas[maxn];
int len,n,m;
int height[maxn];
int k;
void build_Sa()
{
	m=150;
	for(int i=0;i<n;i++)
		rank[i]=data[i],tot[data[i]]+=1;
	for(int i=1;i<=m;i++)
		tot[i]+=tot[i-1];
	for(int i=n-1;i>=0;i--)
		sa[--tot[rank[i]]]=i;
	for(int k=1;k<=n;k<<=1)
	{
		int num=0;
		for(int i=n-k;i<n;i++)	pas[num++]=i;
		for(int i=0;i<n;i++)
			if(sa[i]>=k)	pas[num++]=sa[i]-k;
		for(int i=0;i<=m;i++)	tot[i]=0;
		for(int i=0;i<n;i++)	tot[rank[i]]+=1;
		for(int i=1;i<=m;i++)	tot[i]+=tot[i-1];
		for(int i=n-1;i>=0;i--)
			sa[--tot[rank[pas[i]]]]=pas[i],pas[i]=0;
		swap(pas,rank);
		num=1;rank[sa[0]]=1;
		for(int i=1;i<n;i++)
			if(pas[sa[i]]!=pas[sa[i-1]]||pas[sa[i]+k]!=pas[sa[i-1]+k])		
				rank[sa[i]]=++num;
			else
				rank[sa[i]]=num;
		if(num>=n)	break;
		m=num;
	}
}
void build_LCP()
{
	int h=0;
	/*for(int i=0;i<n;i++)	pas[sa[i]]=i;
	for(int i=0;i<n;i++)
	{
		if(!pas[i])	continue;
		int j=sa[pas[i]-1];
		if(h)	h--;
		while(data[j+h]==data[i+h]&&j+h<n&&i+h<n)	h++;
		height[pas[i]]=h;
	}*/
	for(int i=0;i<n;i++)
	{
		if(rank[i]-1==0)	continue;
		int j=sa[rank[i]-2];
		if(h)	h-=1;
		while(j+h<n&&i+h<n)
			if(data[j+h]!=data[i+h])	break;
			else h+=1;
		height[rank[i]]=h;
	}
}
bool check(int val)
{
	int now=0;
	for(int i=0;i<=n;i++)
	{
		if(height[i]>=val)	now+=1;
		else	now=0;
		if(now>=k-1)	return true;
	}
	return false;
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++)	scanf("%d",&data[i]);
	int l=1,r=n,mid;
	build_Sa();
	build_LCP();
	while(l+1<r)
	{
		mid=(l+r)>>1;
		if(check(mid))	l=mid;
		else r=mid-1;
	}
	printf("%d", check(r) ? r : l  );
}
/*
8 2
1
2
3
2
3
2
3
1
12323231
*/
posted @ 2018-07-07 22:36  Lance1ot  阅读(109)  评论(0编辑  收藏  举报