出现k次以上重复的最长子串 poj 3261

原创 2012年03月22日 15:01:55

先二分答案,然后分组。只要某一组包含的后缀数量大于等于k,表示有解

//出现k次以上重复的最长子串
#include <iostream>
#include <string>
#include <cmath>
#include <map>
using namespace std;
const int N=30000;
int wa[N],wb[N],wv[N],wsum[N];
int height[N],sa[N],rank[N];
int n,k;
int str[N];
int ans;
int cmp(int *r,int a,int b,int l)
{
	return r[a]==r[b] && r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m)
{
	int i,j,p,*x=wa,*y=wb,*t;
	for(i=0;i<m;i++)
		wsum[i]=0;
	for(i=0;i<n;i++)
		wsum[x[i]=r[i]]++;
	for(i=1;i<m;i++)
		wsum[i]+=wsum[i-1];
	for(i=n-1;i>=0;i--)
		sa[--wsum[x[i]]]=i;
	for(j=1,p=1;p<n;j*=2,m=p)
	{
		for(p=0,i=n-j;i<n;i++)
			y[p++]=i;
		for(i=0;i<n;i++)
			if(sa[i]>=j)
				y[p++]=sa[i]-j;
		for(i=0;i<n;i++)
			wv[i]=x[y[i]];
		for(i=0;i<m;i++)
			wsum[i]=0;
		for(i=0;i<n;i++)
			wsum[wv[i]]++;
		for(i=1;i<m;i++)
			wsum[i]+=wsum[i-1];
		for(i=n-1;i>=0;i--)
			sa[--wsum[wv[i]]]=y[i];
		for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
			x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
	}
}
void calheight(int *r,int *sa,int n)
{
	int i,j,k=0;
	for(i=0;i<=n;i++)
		rank[sa[i]]=i;
	for(i=0;i<n;height[rank[i++]]=k)
		for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
bool check(int x)
{
	int i,cnt=1;
	for(i=2;i<=n;i++)
	{
		if(height[i]>=x)
		{
			cnt++;
			if(cnt>=k)
				return 1;
		}
		else
			cnt=1;
	}
	if(cnt>=k)
		return 1;
	return 0;
}




int main()
{
	int i,j,M,l,r,mid;
	while(~scanf("%d%d",&n,&k))
	{
		M=0;
		for(i=0;i<n;i++)
		{
			scanf("%d",&str[i]);
			str[i]++;
			if(M<str[i])
				M=str[i];
		}
		M++;
		str[n]=0;
		da(str,sa,n+1,M);
		calheight(str,sa,n);
		l=0;
		r=n-1;
		while(l<=r)
		{
			mid=(l+r)>>1;
			if(check(mid))
			{
				ans=mid;
				l=mid+1;
			}
			else
			{
				r=mid-1;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}





相关文章推荐

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了...

POJ 3261 Milk Patterns【后缀数组】可重叠的k次最长子串

Description Farmer John has noticed that the quality of milk given by his cows varies from day t...
  • Bcwan_
  • Bcwan_
  • 2016年10月09日 15:02
  • 147

POJ3261 Milk Patterns,后缀数组, 出现k次的重复子串

也是根据height来计算前缀,同时利用二分来检索答案,根据每次二分的最少长度来给height来分组 /***********************************************...
  • neofung
  • neofung
  • 2012年06月02日 22:02
  • 800

POJ 3261 Milk Patterns(后缀数组 重复出现K次字串的长度)

Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7956   ...

POJ 3261 Milk Patterns(可重叠的K次最长重复子串)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove 题目:http://p...

POJ 3261 Milk Patterns ( 后缀数组 + 二分 可重叠的 k 次最长重复子串 )

题意 :给定一个字符串 , 求至少

POJ 3261 Milk Patterns (离散化+后缀数组 可重叠k次最长重复子串)

题意:给出一串长度为n的字符,再给出一个k值,要你求重复次数大于等于k次的最长子串长度 思路:首先离散化,然后采用后缀数组的常用处理方法,二份答案,按照二份值k将height数组分组,对于k是否可行...

【后缀数组求可重叠的k 次最长重复子串】POJ 3261

先二分答案,然后将后缀分成若干组,判断的是有没有一个组的后缀个数不小于k。如果有,那么存在k 个相同的子串满足条件,否则不存在。这个做法的时间复杂度为O(nlogn)。 这里有一个地方要注意的,就是...
  • leolin_
  • leolin_
  • 2012年01月29日 00:38
  • 368

POJ3261——重复K次的子串

题意:给定长度为N的整数串,问至少重复K次的子串最长是多少,重复子串之间可以重迭。求出SA与Height数组,首先将问题转为判定性问题,即:给定长度L,问存不存在长度为L且重复K次的子串。然后二分搜索...

POJ 3261 Milk Patterns 可重叠的k次最长重复子串

后缀数组 的入门题。 先计算好SA和height数组。 然后二分答案。二分的时候,对height进行分组,看存不存在一组的大小大于等于k // // main.cpp // 后缀数组 // ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:出现k次以上重复的最长子串 poj 3261
举报原因:
原因补充:

(最多只允许输入30个字)