poj1743(后缀数组+二分)
2016-08-07 15:43
239 查看
不可重叠最长重复子串
后缀数组后,二分最长长度,在维护长度不小于mid时,判断是否有两个位置之间的差>mid,表示不重叠,由此更新l,r
方法:字符串处理常用二分+后缀数组常用分组
分组的本质就是这个组均包含长度为mid的子串,就是这个组的长度为mid的前缀都相同
后缀数组后,二分最长长度,在维护长度不小于mid时,判断是否有两个位置之间的差>mid,表示不重叠,由此更新l,r
方法:字符串处理常用二分+后缀数组常用分组
分组的本质就是这个组均包含长度为mid的子串,就是这个组的长度为mid的前缀都相同
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const int N=20050; const int inf=0x3f3f3f3f; inline int read() { int ans,f=1;char ch; while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0'; while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0'; return ans*f; } int n,sa ,rank ,height ,s ,t1 ,t2 ,c ,p ; void clear() { memset(p,0,sizeof(p)); memset(sa,0,sizeof(sa)); memset(rank,0,sizeof(rank)); memset(height,0,sizeof(height)); memset(s,0,sizeof(s)); memset(t1,0,sizeof(t1)); memset(t2,0,sizeof(t2)); } void build_sa() { int m=200,*x=t1,*y=t2; for (int i=0;i<m;i++) c[i]=0; for (int i=0;i<n;i++) c[x[i]=s[i]]++; for (int i=1;i<m;i++) c[i]+=c[i-1]; for (int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for (int k=1;k<=n;k<<=1) { int p=0; for (int i=n-k;i<n;i++) y[p++]=i; for (int i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; for (int i=0;i<m;i++) c[i]=0; for (int i=0;i<n;i++) c[x[y[i]]]++; for (int i=1;i<m;i++) c[i]+=c[i-1]; for (int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); x[sa[0]]=0;p=1; for (int i=1;i<n;i++) x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++; if (p>=n) break; m=p; } } void build_height() { int k=0; for (int i=0;i<n;i++) rank[sa[i]]=i; for (int i=0;i<n-1;i++) { if (k)k--; int j=sa[rank[i]-1]; while (s[j+k]==s[i+k]) k++; height[rank[i]]=k; } } bool pan(int mid) { int mx,mi,h=inf; for (int i=1;i<n;i++) { h=min(h,height[i]); if (h<mid) { h=inf; mx=mi=sa[i]; continue; } if (mx<sa[i]) mx=sa[i]; if (mi>sa[i]) mi=sa[i]; if (mx-mi>mid) return true; } return false; } void debug() { for (int i=1;i<n;i++) { for (int j=sa[i];j<n;j++) printf("%d ",s[j]); printf("\n"); } } int main() { while ((n=read())!=0) { clear(); for (int i=0;i<n;i++) p[i]=read(); if (n==1) {printf("0\n");continue;} n--; for (int i=0;i<n;i++) s[i]=p[i+1]-p[i]+90; s[n++]=0; build_sa(); //debug(); build_height(); int ans=0,l=4,r=n,mid; while (l<=r) { mid=(l+r)>>1; if (pan(mid)) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans?ans+1:0); } return 0; }
相关文章推荐
- 【POJ1743】Musical Theme(后缀数组,二分)
- 【POJ1743】Musical Theme【后缀数组】【二分】
- poj1743(后缀数组+二分)
- poj1743(后缀数组+二分--不可重叠最长重复子串)
- 【POJ1743】Musical Themes 乐曲主题 后缀数组、 (也可以用hash+二分做的~)
- poj1743 Musical Theme(后缀数组+二分判定)
- POJ 3450 Corporate Identity(后缀数组+二分)
- poj 3450 Corporate Identity(后缀数组+二分)
- [BZOJ4556][Tjoi2016&Heoi2016]字符串(后缀数组+二分+st表+主席树)
- SPOJ220---Relevant Phrases of Annihilation(后缀数组+二分,对后缀分组)
- 【SPOJ220】Relevant Phrases of Annihilation(后缀数组,二分)
- poj3261(后缀数组+二分)
- [SPOJ220]PHRASES(后缀数组+二分)
- POJ 3261 - Milk Patterns 求指定重复次数的最长子串,后缀数组+二分 or 线段树
- POJ1743Musical Theme求解不重叠的最长子串长度(后缀数组+二分求解)
- BZOJ3998 TJOI2015弦论(后缀数组+二分答案)
- poj1743 Musical Theme(后缀数组--不可重叠最长重复子串+二分)
- BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )
- poj1745(后缀数组+二分)
- POJ 1226 Substrings(后缀数组+二分)