【后缀数组】不可重叠最长重复子串
来源:互联网 发布:8寸windows平板 编辑:程序博客网 时间:2024/06/07 17:52
hz2016评测《《点击访问caioj《《点击访问这题阴森可怕,两个后缀可以不相同?哦天哪,怎么判断呢。于是,某个聪明的人发现,后缀中两两字符的ANSI值的差是相等的,于是我们可以维护一个由差值组成的后缀数组。所以呢,我们就可以用后缀数组解这道题了,但是这一题,我们还要引入一个新的概念height数组和h数组。height数组的定义就是排名为 i 与 i-1 的最长公共前缀。h就是代表排名为 i 的后缀与其前一个后缀的最长前缀#include<map>#include<queue>#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define Maxchar 28192 //20000 +2^13#define Maxs 30#define mes(x,y) memset(x,y,sizeof(x));#define mpy(x,y) memcpy(x,y,sizeof(x))#define INF 2147483647using namespace std; int n,a[Maxchar+1],tt[Maxchar+1],Rank[Maxchar+1],sa1[Maxchar+1],Rank2[Maxchar+1],sa2[Maxchar+1],Rsort[Maxchar+1];void get_sa(int n,int m){ memcpy(Rank,a,sizeof(Rank)); memset(Rsort,0,sizeof(Rsort)); for(int i=1;i<=n;i++)Rsort[Rank[i]]++; for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1]; for(int i=n;i>=1;i--)sa1[Rsort[Rank[i]]--]=i; int ln=1,p=0; while(p<n){ int k=0; for(int i=n-ln+1;i<=n;i++)sa2[++k]=i; for(int i=1;i<=n;i++)if(sa1[i]-ln>0)sa2[++k]=sa1[i]-ln; memset(Rsort,0,sizeof(Rsort)); for(int i=1;i<=n;i++)Rsort[Rank[i]]++; for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1]; for(int i=n;i>=1;i--)sa1[Rsort[Rank[sa2[i]]]--]=sa2[i]; for(int i=1;i<=n;i++)tt[i]=Rank[i]; p=1;Rank[sa1[1]]=1; for(int i=2;i<=n;i++){ if(tt[sa1[i]]!=tt[sa1[i-1]]||tt[sa1[i]+ln]!=tt[sa1[i-1]+ln])p++; Rank[sa1[i]]=p; } m=p;ln*=2; }} //上面是基础的后缀数组模版。 int height[Maxchar+1];void get_he(int n){ int j,k=0; for(int i=2;i<=n;i++){ j=sa1[Rank[i]-1]; if(k!=0)k--; while(a[j+k]==a[i+k])k++;//匹配最初前缀 //h数组的定义就是后缀 i 和后缀 i-1的最长前缀 height[Rank[i]]=k;//记录两个后缀的最长前缀 //最后记录下排名为 i 的后缀与其前一个后缀的最长前缀 }}//就是新的h数组,这个才是后缀数组的真谛。 bool check(int k,int n){ for(int i=2;i<=n;i++){ if(height[i]>=k){ for(int j=i-1;j>=2;j--){ if(abs(sa1[i]-sa1[j])>=k)return true;//满足直接true if(height[j]<k)break;//二分假如现在条件不满足就跳出 } } } return false;}int main(){while(scanf("%d",&n)!=EOF){if(n==0)break;for(int i=1;i<=n;i++)scanf("%d",&a[i]);int mmax=-9999999; for(int i=1;i<n;i++){ a[i]=a[i+1]-a[i]+88; if(mmax<a[i])mmax=a[i]; //取maxx是为了减少后缀数组的基数排序时间复杂度 } a[n]=0;n--; get_sa(n,mmax);get_he(n); //然后通过二分枚举答案 int l=1,r=n,ans=1; while(l<=r){ int mid=(l+r)/2; if(check(mid,n)==true){//二分枚举长度 ans=mid;l=mid+1; } else r=mid-1; } if(ans<4)printf("0\n"); else printf("%d\n",ans+1);} return 0;}
查看原文:http://hz2016.tk/blog/?p=29
阅读全文
0 0
- poj1743(后缀数组+二分--不可重叠最长重复子串)
- 不可重叠的最长重复子串(后缀数组)
- 后缀数组(不可重叠最长重复子串)
- 后缀数组 最长不可重叠重复子串问题
- 【后缀数组】不可重叠最长重复子串
- 后缀数组模版 及 可重叠和不可重叠最长重复子串【for_wind】
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
- Hiho 121 后缀数组二·重复旋律2(最长不可重叠重复子串问题)
- 【后缀数组求不可重叠最长重复子串】POJ 1743
- POJ 1743 Musical Theme(后缀数组求不可重叠最长重复子串)
- poj 1743 字符串 后缀数组 不可重叠最长重复子串
- PKU1743(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 (后缀数组求不可重叠最长重复子串)
- [ZJOI2006]物流运输 (最短路+dp)
- [SDUT](2121)数据结构实验之链表六:有序链表的建立
- Office转换技巧之转换pdf格式文件的方法分享
- codeforce 864C Bus(模拟)
- 【BZOJ 4569】【SCOI】【萌萌哒】【并查集】【倍增均摊优化】
- 【后缀数组】不可重叠最长重复子串
- Manthan, Codefest 17
- flume-ng+Hadoop实现日志收集
- Ubuntu14.04 telnet 服务安装
- 冒泡排序
- opencv3.3 svm的使用
- unity 收货币动画
- git使用方式
- C-COT核心思想