您的位置:首页 > 其它

poj_1743_Musical Theme(后缀数组)

2016-08-12 20:48 375 查看

题目链接:poj_1743_Musical Theme

题意:

给你一串数字,让你找最长的变化相同不重叠的子串,至少长度为5

题解:

处理数据后用后缀数组加二分答案,然后用height数组check答案,运用height数组求相同不重叠的子串经典运用

 

#include<cstdio>
#include<algorithm>
#define F(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

namespace suffixarray{
#define FN(n) for(int i=0;i<n;i++)
const int N =2E4+7;
int rnk
,sa
,height
,c
,s
;
void getsa(int n,int m,int *x=rnk,int *y=height){
FN(m)c[i]=0;FN(n)c[x[i]=s[i]]++;FN(m)c[i+1]+=c[i];
for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
for(int k=1,p;p=0,k<=n;k=p>=n?N:k<<1,m=p){
for(int i=n-k;i<n;i++)y[p++]=i;
FN(n)if(sa[i]>=k)y[p++]=sa[i]-k;
FN(m)c[i]=0;FN(n)c[x[y[i]]]++;FN(m)c[i+1]+=c[i];
for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
swap(x,y),p=1,x[sa[0]]=0;
for(int i=1;i<n;i++)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
}
FN(n)rnk[sa[i]]=i;
for(int i=0,j,k=0;i<n-1;height[rnk[i++]]=k)
for(k=k?k-1:k,j=sa[rnk[i]-1];s[i+k]==s[j+k];k++);
}
}

using namespace suffixarray;
int n;
inline void upd(int &a,int b){if(a>b)a=b;}
inline void upu(int &a,int b){if(a<b)a=b;}

inline bool check(int x)
{
int l=N,r=0;
F(i,1,n)
{
if(height[i]>=x)
{
upd(l,sa[i]),upu(r,sa[i]);
if(r-l>=x)return 1;
}else l=r=sa[i];
}
return 0;
}

int main()
{
while(scanf("%d",&n),n)
{
F(i,0,n-1)scanf("%d",s+i);
if(n<10){puts("0");continue;}
F(i,0,n-2)s[i]=s[i+1]-s[i]+89;
s[--n]=0,getsa(n+1,200);
int l=4,r=n,mid;
while(l<=r)mid=(l+r)>>1,check(mid)?l=mid+1:r=mid-1;
printf("%d\n",l<5?0:l);
}
return 0;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: