1
7
2016
0

【poj1743】 Musical Theme

题意:给你一个数字串,找到最长长度且不重叠的两个子串,使得这两个子串变化相同。

什么叫变化相同呢,就是比如{1,3,4,6,9}与{5,7,8,10,13}就是变化相同的。

首先我们可以把数字串的相邻两个相减,得到的新序列。我们只要在这个新序列中找到最长的相等的且不重叠的两个子串。我们可以先二分答案,然后由于lcp的性质,height可以分为若干组,每组中的height都是大于等于mid的,只要同一组存在两个数使得它们在原串的的位置差大于mid,就可行。

代码:

 

#include<cstdio>
#include<algorithm>
using namespace std;
int n,x,y;
int wa[20010],wb[20010],ws[20010],wv[20010],r[20010],sa[20010],rank[20010],height[20010];
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++) ws[i]=0;
	for (i=0;i<n;i++) ws[x[i]=r[i]]++;
	for (i=1;i<m;i++) ws[i]+=ws[i-1];
	for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
	for (j=1,p=1;p<n;j*=2,m=p)
	{
		p=0;
		for (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++) ws[i]=0;
		for (i=0;i<n;i++) ws[wv[i]]++;
		for (i=1;i<m;i++) ws[i]+=ws[i-1];
		for (i=n-1;i>=0;i--) sa[--ws[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=1;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++);
}
int check(int *sa,int n,int mid)
{
	int Min=sa[1],Max=sa[1];
	for (int i=2;i<=n;i++)
	{
		if (height[i]<mid) Min=Max=sa[i];else
		{
			Max=max(Max,sa[i]);
			Min=min(Min,sa[i]);
			if (Max-Min>mid) return 1;
		}
	}
	return 0;
}
int main()
{
	while (1)
	{
		scanf("%d",&n);
		if (!n) break;
		scanf("%d",&y);
		n--;
		for (int i=0;i<n;i++)
		{
			scanf("%d",&x);
			r[i]=x-y+100;
			y=x;
		}
		r[n]=0;
		da(r,sa,n+1,200);
		calheight(r,sa,n);
		int l=1,r=n/2;
		while (l<r)
		{
			int mid=((l+r)>>1)+1;
			if (check(sa,n,mid)) l=mid;else r=mid-1;
		}
		if (r>=4) printf("%d\n",r+1);else printf("0\n");
	}
}
Category: 后缀数组 | Tags: | Read Count: 271

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com