您的位置:首页 > 其它

poj1743 Musical Theme 后缀数组的应用(求最长不重叠重复子串)

2013-08-23 11:19 543 查看
题目链接:http://poj.org/problem?id=1743

题目理解起来比较有困难,其实就是求最长有N(1<=N<=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。

*“主题”是整个音符序列的一个子串,它需要满足如下条件:
*1.长度至少为5个音符
*2.在乐曲中重复出现(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值。)
*3.重复出现的同一主题不能有公共部分。
*
所以1,2,3,4,5和6,7,8,9,10是同一个主题
思路:
先转化成相邻两项的差值,然后就是找不可重叠重复子串。
详细解释可以参考:http://hi.baidu.com/ahnkftravhdhkyr/item/346115451d98e8fedc0f6ccd




#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
usingnamespacestd;
#definemaxn20010

intwa[maxn],wb[maxn],wv[maxn],wq[maxn];
intheight[maxn];
ints[maxn];
intrank[maxn];
intsa[maxn];
boolcmp(int*r,inta,intb,intl)
{returnr[a]==r[b]&&r[a+l]==r[b+l];}
voidda(int*s,int*sa,intn,intm)
{
inti,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++)wq[i]=0;
for(i=0;i<n;i++)wq[x[i]=s[i]]++;
for(i=0;i<m;i++)wq[i]+=wq[i-1];
for(i=n-1;i>=0;i--)sa[--wq[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++)wq[i]=0;
for(i=0;i<n;i++)wq[wv[i]]++;
for(i=1;i<m;i++)wq[i]+=wq[i-1];
for(i=n-1;i>0;i--)sa[--wq[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++;
}

return;
}
voidgetHeight(int*s,intn)
{
inti,j,k=0;
for(i=1;i<=n;i++)rank[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k)k--;
j=sa[rank[i]-1];
while(s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
}
boolcheck(intn,intk)
{
intMax=sa[1],Min=sa[1];
for(inti=2;i<=n;i++)
{
if(height[i]<k)Max=Min=sa[i];
else
{
if(sa[i]<Min)Min=sa[i];
if(sa[i]>Max)Max=sa[i];
if(Max-Min>k)return1;
}
}
return0;
}
intmain()
{
intn;
while(scanf("%d",&n)!=EOF&&n)
{
for(inti=0;i<n;i++)scanf("%d",&s[i]);
for(inti=0;i<n-1;i++)s[i]=s[i+1]-s[i]+100;

n--;
s
=0;
da(s,sa,n+1,200);
getHeight(s,n);
intans=-1;
intlow=4,high=n/2;
while(low<=high)
{
intmid=(low+high)/2;
if(check(n,mid))
{
ans=mid;
low=mid+1;
}
elsehigh=mid-1;
}
if(ans<4)cout<<"0"<<endl;
elsecout<<ans+1<<endl;
}
return0;
}





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