POJ-1743 Musical Theme,后缀数组+二分!
来源:互联网 发布:国家软件重点企业 编辑:程序博客网 时间:2024/04/29 00:24
Musical Theme
人生第一道后缀数组的题,采用大众化思想姿势极其猥琐。
题意:给你n个数,问其中是否存在一个子序列,这个子序列加上或者减去一个数与另一个子序列一样。要求两个子序列不能有重叠的部分。求这个子序列最长的长度。
思路:有点像KMP,先将所有的数之间的差(再加上88)存在一个数组中,然后对这个数组进行构造后缀数组。我们知道height[]数组的含义是:排名为i的这个后缀与排名为i-1的这个后缀的最长公共前缀。而我们要求的是不重叠,怎么解决这个问题呢 ,我们可以二分答案,将问题变成二分判定型。引用罗穗骞的论文:
先二分答案,把题目变成判定性问题:判断是否存在两个长度为k的子串是相同的,且不重叠。解决这个问题的关键还是利用height数组。把排序后的后缀分成若干组,其中每组的后缀之间的height值都不小于k。容易看出,有希望成为最长公共前缀不小于k的两个后缀一定在同一组。然后对于每组后缀,只须判断每个后缀的sa值的最大值和最小值之差是否不小于k。如果有一组满足,则说明存在,否则不存在。整个做法的时间复杂度为O(nlogn)。
需要注意的是此题m的范围是88*2。
int a[N],s[N];int sa[N],t[N],t1[N],c[N],n,m=88*3;void build(){ int i,*x=t,*y=t1; memset(c,0,sizeof(c)); for(i=0; i<n; i++) c[x[i]=s[i]]++; for(i=1; i<m; i++) c[i]+=c[i-1]; for(i=n-1; i>=0; i--) sa[--c[x[i]]]=i; for(int k=1; k<=n; k<<=1) { int p=0; for(i=n-k; i<n; i++) y[p++]=i; for(i=0; i<n; i++) if(sa[i]>=k) y[p++]=sa[i]-k; memset(c,0,sizeof(c)); for(i=0; i<n; i++) c[x[y[i]]]++; for(i=1; i<m; i++) c[i]+=c[i-1]; for(i=n-1; i>=0; i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1,x[sa[0]]=0; for(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++; if(p>=n) break; m=p; }}int Rank[N],height[N];void get_height(){ int k=0; for(int i=0;i<n;i++) Rank[sa[i]]=i; for(int i=0;i<n;i++) { if(k) k--; int j=sa[Rank[i]-1]; while(s[i+k]==s[j+k]) k++; height[Rank[i]]=k; }}int find(int k){ int i=1; while(i<=n) { while(i<=n&&height[i]<k) i++; if(i>n) return 0; int ma=sa[i-1],mi=sa[i-1]; while(i<=n&&height[i]>=k) { ma=max(ma,sa[i]); mi=min(mi,sa[i]); i++; } if(ma-mi>=k) return 1; } return 0;}int main(){ while(~scanf("%d",&n)&&n) { for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n-1;i++) s[i]=a[i+1]-a[i]+88; n--; build(); get_height(); int l=0,r=n/2; while(l<r) { int mid=(l+r+1)/2; if(find(mid)) l=mid; else r=mid-1; } l=l>=4?l+1:0; printf("%d\n",l); } return 0;}心力交瘁。。。。。。卒
0 0
- [后缀数组+二分] poj 1743 Musical Theme
- POJ 1743 Musical Theme 后缀数组+二分
- poj 1743 Musical Theme(后缀数组、二分)
- POJ-1743 Musical Theme,后缀数组+二分!
- POJ 1743 Musical Theme <后缀数组+二分>
- POJ 1743 Musical Theme 后缀数组 二分
- POJ 1743 Musical Theme 后缀数组+二分
- POJ 1743 Musical Theme(二分+后缀数组)
- poj 1743 Musical Theme(后缀数组+二分)
- poj 1743 Musical Theme (后缀数组+二分答案)
- Poj 1743Musical Theme|后缀数组|二分答案
- POJ 1743 Musical Theme(二分+后缀数组)
- POJ-1743-Musical Theme(后缀数组+二分)
- POJ 1743 Musical Theme(后缀数组+二分)
- POJ 1743 Musical Theme (二分后缀数组LCP)
- Poj 1743 Musical Theme(后缀数组+二分答案)
- POJ 1743 Musical Theme (后缀数组 + 二分)
- poj 1743 Musical Theme (二分+后缀数组)
- SVN与VSS并用进行代码管理
- 数位dp-P2518 [HAOI2010]计数
- System.currentTimeMillis()计算方式与时间的单位转换
- 错误 implicit declaration of function 'class_create' implicit declaration of function 'class_device_
- Android添加@联系人功能
- POJ-1743 Musical Theme,后缀数组+二分!
- 三分模版
- 移动端兼容性
- 开启openssl
- IE中的for...in... Bug
- 我眼中的设计模式(5)
- Execl获取真实行数
- .Net下的Windows服务程序开发指南.
- Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享