[pku1743]不可重叠最长重复子串
来源:互联网 发布:c语言三角形判断 编辑:程序博客网 时间:2024/06/06 08:26
题目还是自己找吧,我有点懒啦。
今天我写一下后缀数组的博客,php的更新鲜停一天。
给定一个字符串,求最长重复子串,这两个子串不能重叠。
算法分析:
先二分答案,把题目变成判定性问题:判断是否存在两个长度为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
- [pku1743]不可重叠最长重复子串
- PKU1743(Musical Theme)求不可重叠最长重复子串(后缀数组+二分)
- 后缀数组之最长重复不重叠子串 PKU1743
- [poj1743]不可重叠最长重复子串
- POJ 1743 不可重叠最长重复子串
- poj1743(后缀数组+二分--不可重叠最长重复子串)
- 不可重叠的最长重复子串(后缀数组)
- poj 1743 Musical Theme (不可重叠最长重复子串)
- poj1743Musical Theme(不可重叠最长重复子串)
- 后缀数组(不可重叠最长重复子串)
- 后缀数组 最长不可重叠重复子串问题
- poj 1743 不可重叠最长重复子串
- 【后缀数组】不可重叠最长重复子串
- 后缀数组模版 及 可重叠和不可重叠最长重复子串【for_wind】
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
- Hiho 121 后缀数组二·重复旋律2(最长不可重叠重复子串问题)
- 【后缀数组求不可重叠最长重复子串】POJ 1743
- POJ 1743 Musical Theme(后缀数组求不可重叠最长重复子串)
- Bootstrap—使用按钮组
- Hbase葱岭探秘--JavaApi实践
- 广义霍夫变换目标匹配
- 回归算法应用场景实例二十则
- docker命令
- [pku1743]不可重叠最长重复子串
- [LeetCode] 63. Unique Paths II
- 微软等数据结构+算法面试100题全部答案集锦
- VS远程调试连接失败
- JS判断当前浏览器类型
- 51Nod 1393 0和1相等串
- 数据结构实验之排序五:归并求逆序数
- Weblogic 中部署项目的三种方式
- 鸟人的Android揭秘(3)——Android 编译环境搭建