后缀数组(不可重叠最长重复子串)
来源:互联网 发布:linux自动登录ssh脚本 编辑:程序博客网 时间:2024/06/07 06:22
poj 1743
二分答案,把题目变成判定性问题:判断是否
存在两个长度为k的子串是相同的,且不重叠。解决这个问题的关键还是利用
height数组。把排序后的后缀分成若干组,其中每组的后缀之间的height值都
不小于k。
有希望成为最长公共前缀不小于k的两个后缀一定在同一组。然
后对于每组后缀,只须判断每个后缀的sa值的最大值和最小值之差是否不小于
k。如果有一组满足,则说明存在,否则不存在。
#include<cstdio>//sa为后缀数组,把后缀从小到大排序把后缀开头存起来,rank为名次数组,以i开头的后缀在所有后缀中排第几#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define F(x) ((x)/3+((x)%3==1?0:tb))#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)using namespace std;const int maxn=1e6+10;int wa[maxn],wb[maxn],ww[maxn],wv[maxn],n;int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int *r,int *sa,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; for(i=0; i<m; i++) ww[i]=0; for(i=0; i<n; i++) ww[x[i]=r[i]]++; for(i=1; i<m; i++) ww[i]+=ww[i-1]; for(i=n-1; i>=0; i--) sa[--ww[x[i]]]=i; //处理长度为一的字符串,得到sa数组 for(j=1,p=1; p<n; j*=2,m=p) //倍增法求sa { for(p=0,i=n-j; i<n; i++) y[p++]=i; for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;//利用上次的sa直接求出按第二个关键字排序 for(i=0; i<n; i++) wv[i]=x[y[i]]; //第二关键字的排序得出第一关键字的顺序 for(i=0; i<m; i++) ww[i]=0; for(i=0; i<n; i++) ww[wv[i]]++; for(i=1; i<m; i++) ww[i]+=ww[i-1]; for(i=n-1; i>=0; i--) sa[--ww[wv[i]]]=y[i]; //根据第一关键字的顺序排出sa数组的顺序 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++) //更新x数组 x为rank数组 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } return ;}int h[maxn];//也就是排名相邻的两个后缀的最长公共前缀sa[i]和sa[i-1]int Rank[maxn];//名次数组void get_height(int *r,int *sa,int n){ int k=0,i,j; for(int i=1; i<=n; i++) Rank[sa[i]]=i; for(int i=0; i<n; h[Rank[i++]]=k) for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++) ; return ;}int a[maxn];int sa[maxn],r[maxn];int judge(int mid){ int mn,mx,j; for(int i=1; i<=n; i=j) { while(i<=n&&h[i]<mid)//排除最长前缀小于mid的 i++; j=i; mn=n;//记录同一组中sa的最小值 mx=0;//记录同一组中sa的最大值 if(i==n+1) break; mn=min(mn,sa[i-1]); mx=max(mx,sa[i-1]); while(j<=n&&h[j]>=mid)//大于mid的分在同一组 { mn=min(mn,sa[j]); mx=max(mx,sa[j]); j++; } if(mx-mn>=mid)//如果不重复返回1 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++) { a[i]=a[i+1]-a[i]+89; } n--; a[n]=0; da(a,sa,n+1,180); get_height(a,sa,n); int l=0; int R=n-1; while(l<=R)//二分枚举长度 { int mid=(l+R)>>1; if(judge(mid)) l=mid+1; else R=mid-1; } int ans=R; if(ans>=4) printf("%d\n",ans+1); else printf("0\n"); }}
0 0
- 不可重叠的最长重复子串(后缀数组)
- 后缀数组(不可重叠最长重复子串)
- poj1743(后缀数组+二分--不可重叠最长重复子串)
- 后缀数组 最长不可重叠重复子串问题
- 【后缀数组】不可重叠最长重复子串
- POJ 1743 Musical Theme(后缀数组求不可重叠最长重复子串)
- POJ 1743 Musical Theme (后缀数组加二分求不可重叠最长重复子串)
- 后缀数组(不可重叠最长重复子串)——POJ 1743
- poj1743 Musical Theme(后缀数组--不可重叠最长重复子串+二分)
- POJ - 1743 - Musical Theme(后缀数组 - 不可重叠最长重复子串)
- POJ 1743 Musical Theme(不可重叠最长重复子串 后缀数组)
- poj1743(后缀数组:最长不可重叠子串长度)
- 后缀数组模版 及 可重叠和不可重叠最长重复子串【for_wind】
- 后缀数组(不可重叠重复子串)poj1743
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
- Hiho 121 后缀数组二·重复旋律2(最长不可重叠重复子串问题)
- 【后缀数组求不可重叠最长重复子串】POJ 1743
- poj 1743 字符串 后缀数组 不可重叠最长重复子串
- 【leetcode】46. Permutations 【回溯问题的通用方法】【java】
- Python金融大数据分析-PCA分析
- 一步一步学习数据结构(4)-树和二叉树基础知识
- POJ 1942Paths on a Grid(组合数学)
- window下eclipse安装python插件
- 后缀数组(不可重叠最长重复子串)
- 设备驱动中的i2c(kernel-4.7)
- TCP协议与UDP协议的异同
- mongodb中的populate方法
- linux c之shm共享内存的使用例子
- Spring AOP
- mysql 数据库的安装与配置 有关msi文件start service 停滞不前的问题及其解决办法
- Java 8之Stream适用场景
- 深度相机-PMD、Kinect、Camcube3.0的比较