首页 > 代码库 > POJ-1743 Musical Theme(后缀数组)
POJ-1743 Musical Theme(后缀数组)
题目大意:给一个整数序列,找出最长的连续变化相同的、至少出现两次并且不相重叠一个子序列。
题目分析:二分枚举长度进行判定。
代码如下:
# include<iostream># include<cstdio># include<cstring># include<algorithm>using namespace std;# define mid (l+(r-l)/2)const int N=20000;int SA[N+5],height[N+5];int *rk,*tSA;int n,a[N+5],cnt[N+5];bool same(int i,int j,int k){ if(tSA[i]!=tSA[j]) return false; if(i+k>=n&&j+k>=n) return true; if(i+k>=n&&j+k<n) return false; if(i+k<n&&j+k>=n) return false; return tSA[i+k]==tSA[j+k];}void buildSA(){ int m=180; for(int i=0;i<m;++i) cnt[i]=0; for(int i=0;i<n;++i) ++cnt[rk[i]=a[i]]; for(int i=1;i<m;++i) cnt[i]+=cnt[i-1]; for(int i=n-1;i>=0;--i) SA[--cnt[rk[i]]]=i; for(int k=1;k<n;k<<=1){ int p=0; for(int i=n-k;i<n;++i) tSA[p++]=i; for(int i=0;i<n;++i) if(SA[i]>=k) tSA[p++]=SA[i]-k; for(int i=0;i<m;++i) cnt[i]=0; for(int i=0;i<n;++i) ++cnt[rk[tSA[i]]]; for(int i=1;i<m;++i) cnt[i]+=cnt[i-1]; for(int i=n-1;i>=0;--i) SA[--cnt[rk[tSA[i]]]]=tSA[i]; swap(rk,tSA); p=1; rk[SA[0]]=0; for(int i=1;i<n;++i){ if(same(SA[i],SA[i-1],k)) rk[SA[i]]=p-1; else rk[SA[i]]=p++; } if(p>=n) break; m=p; }}void getHeight(){ for(int i=0;i<n;++i) rk[SA[i]]=i; int k=0; height[0]=0; for(int i=0;i<n;++i){ if(rk[i]==0) k=0; else{ if(k) --k; int j=SA[rk[i]-1]; while(i+k<n&&j+k<n&&a[i+k]==a[j+k]) ++k; height[rk[i]]=k; } }}bool ok(int x){ int maxn=SA[0],minn=SA[0]; for(int i=1;i<n;++i){ if(minn+x<maxn) return true; if(height[i]>=x){ maxn=max(maxn,SA[i]); minn=min(minn,SA[i]); }else{ maxn=minn=SA[i]; } } return minn+x<maxn;}void init(){ rk=new int[n+5]; tSA=new int[n+5];}void destroy(){ delete []rk; delete []tSA;}int main(){ while(scanf("%d",&n)&&n) { init(); for(int i=0;i<n;++i){ scanf("%d",a+i); --a[i]; } --n; int temp=a[0]; for(int i=0;i<n;++i){ a[i]=a[i+1]-temp+87; temp=a[i+1]; } buildSA(); getHeight(); //二分枚举最短的不满足条件的 int l=4,r=n; while(l<r){ if(ok(mid)) l=mid+1; else r=mid; } printf("%d\n",l>=5?l:0); destroy(); } return 0;}
POJ-1743 Musical Theme(后缀数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。