[poj1743]不可重叠最长重复子串
来源:互联网 发布:一开守望先锋网络就卡 编辑:程序博客网 时间:2024/06/05 15:16
懒死了。
http://poj.org/problem?id=1743
题目鲁鲁拉。
(1)不可重叠最长重复子串(pku1743)
给定一个字符串,求最长重复子串,这两个子串不能重叠。
算法分析:
先二分答案,把题目变成判定性问题:判断是否存在两个长度为k的子串是相同的,且不重叠。解决这个问题的关键还是利用height数组。把排序后的后缀分成若干组,其中每组的后缀之间的height值都不小于k。例如,字符串为“aabaaaab”,当k=2时,后缀分成了4组,如图5所示。
容易看出,有希望成为最长公共前缀不小于k的两个后缀一定在同一组。然后对于每组后缀,只须判断每个后缀的sa值的最大值和最小值之差是否不小于k。如果有一组满足,则说明存在,否则不存在。整个做法的时间复杂度为O(nlogn)。
#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int a[210000],wr[210000],mc[210000],JS[210000],sa[210000],y[210000],height[210000];bool cmp(int k1,int k2,int ln){ return wr[k1]==wr[k2]&&wr[k1+ln]==wr[k2+ln];}void get_sa(int n,int m){//构建SA后缀数组 int i,k,p,ln; //memcpy(mc,a,sizeof(a)); for(i=1;i<=n;i++)mc[i]=a[i]; //a数组:原字符串,mc名次数组 for(i=0;i<=m;i++)JS[i]=0; for(i=1;i<=n;i++)JS[mc[i]]++; for(i=1;i<=m;i++)JS[i]+=JS[i-1]; for(i=n;i>=1;i--)sa[JS[mc[i]]--]=i; //以上四句为基数排序,不懂的看flash ln=1;p=0; //ln为当前子串的长度,p表示有多少不相同的子串 while(p<n){ for(k=0,i=n-ln+1;i<=n;i++)y[++k]=i; for(i=1;i<=n;i++)if(sa[i]-ln>0)y[++k]=sa[i]-ln; for(i=1;i<=n;i++)wr[i]=mc[y[i]]; //数组y保存的是对第二关键字排序的结果 。 //数组wr保存的是对第二关键字排序后的mc值 //以下为对第一关键字排序 for(i=0;i<=m;i++)JS[i]=0; for(i=1;i<=n;i++)JS[wr[i]]++; for(i=1;i<=m;i++)JS[i]+=JS[i-1]; for(i=n;i>=1;i--)sa[JS[wr[i]]--]=y[i]; memcpy(wr,mc,sizeof(wr)); p=1;mc[sa[1]]=1; for(i=2;i<=n;i++){ if(!cmp(sa[i],sa[i-1],ln))p++; mc[sa[i]]=p; } //得到新的mc数组 m=p;ln*=2; } a[0]=0;sa[0]=0;}void get_he(int n){ int i,j,k=0; for(i=1;i<=n;i++){ j=sa[mc[i]-1]; if(k)k--; while(a[j+k]==a[i+k])k++; height[mc[i]]=k; }}bool check(int n,int k){ int maxx=sa[1],minn=sa[1]; for(int i=2;i<=n;i++){ if(height[i]<k)maxx=minn=sa[i]; else{ minn=min(minn,sa[i]); maxx=max(maxx,sa[i]); if(maxx-minn>k)return true; } } return false;}void erfen(int n){ int l,r,mid,ans; l=1;r=n; while(l<=r){ mid=(l+r)/2; if(check(n,mid)){ ans=mid; l=mid+1; } else r=mid-1; } if(ans>=4)printf("%d\n",ans+1); else printf("0\n");}int main(){ int n,k,p; while (scanf("%d",&n)!=EOF){ if(n==0)break; memset(mc,0,sizeof(mc)); memset(a,0,sizeof(a)); memset(sa,0,sizeof(sa)); scanf("%d",&p); for(int i=1;i<n;i++){ scanf("%d",&k); a[i]=k-p+100; p=k; } get_sa(n-1,200); get_he(n-1); erfen(n-1); } return 0;}
0 0
- [poj1743]不可重叠最长重复子串
- poj1743(后缀数组+二分--不可重叠最长重复子串)
- 后缀数组经典题---不可重叠最长重复子串 poj1743
- poj1743 Musical Theme(后缀数组--不可重叠最长重复子串+二分)
- 【poj1743】Musical Theme 后缀数组/不可重叠最长重复子串 + 双指针扫描
- poj1743(后缀数组:最长不可重叠子串长度)
- 后缀数组(不可重叠重复子串)poj1743
- POJ1743——不可重迭的最长重复子串
- [pku1743]不可重叠最长重复子串
- poj1743 Musical Theme 后缀数组之不可重叠最长公共子串
- POJ1743 Musical Theme,后缀数组,最长重复不重叠子串,二分检索答案
- poj1743最长不重复公共子串
- POJ 1743 不可重叠最长重复子串
- 不可重叠的最长重复子串(后缀数组)
- poj 1743 Musical Theme (不可重叠最长重复子串)
- poj1743Musical Theme(不可重叠最长重复子串)
- 后缀数组(不可重叠最长重复子串)
- 后缀数组 最长不可重叠重复子串问题
- 编写一个函数,可以实现左旋字符串中的k个字符。
- 关于视频录制的一些尝试
- 第十五周OJ项目J字符串的比较
- Java学习笔记 --- 理解字符串池
- 爱情这杯酒谁喝都得醉
- [poj1743]不可重叠最长重复子串
- Android 从本地和服务器拉取数据显示
- js简单验证码
- spring 很详细的事务管理
- 在阿里云centOs上部署项目环境<三>
- 如何教计算机认识手写数字(下)
- 线程间的状态转换
- AttributeError: 'module' object has no attribute 'VideoWriter_fourcc'
- Sqlite的使用(二)