poj3261(后缀数组--可重叠的k次最长重复子串+二分+离散化)
2015-09-04 16:29
429 查看
题目链接:点击打开链接
题意描述:给定一个字符串,找出可重叠k次的最长重复子串?
解题思路:后缀数组+二分+离散化
代码:
题意描述:给定一个字符串,找出可重叠k次的最长重复子串?
解题思路:后缀数组+二分+离散化
代码:
#include <cstdio> #include <algorithm> #include <iostream> #define maxn 20010 using namespace std; int wa[maxn],wb[maxn],wv[maxn],ww[maxn]; 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; for(j=1,p=1; p<n; j*=2,m=p) { 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; 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]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; ++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } return ; } int ranks[maxn],height[maxn]; void calheight(int* r,int* sa,int n) { int i,j,k=0; for(i=1; i<=n; ++i) ranks[sa[i]]=i; for(i=0; i<n; height[ranks[i++]]=k) for(k?k--:0,j=sa[ranks[i]-1]; r[i+k]==r[j+k]; k++); return; } int sa[maxn]; int check(int n,int k,int cc) { int x=0; for(int i=2; i<=n; ++i) { if(height[i]<k) x=0; else { x=(x==0?2:(x+1)); if(x>=cc) return true; } } return false; } struct node { int v; int id; int rk; } st[maxn]; bool cmp1(node a,node b){ return a.v<b.v; } bool cmp2(node a,node b){ return a.id<b.id; } int n,str[maxn],cc; int main() { while(scanf("%d%d",&n,&cc)!=EOF) { for(int i=0; i<n; ++i) { scanf("%d",&st[i].v); st[i].id=i; } sort(st,st+n,cmp1); st[0].rk=1; int m=2; for(int i=1; i<n; ++i) { if(st[i].v==st[i-1].v) st[i].rk=st[i-1].rk; else st[i].rk=m++; } sort(st,st+n,cmp2); for(int i=0;i<n;++i) str[i]=st[i].rk; str =0; da(str,sa,n+1,m); calheight(str,sa,n); int l=0,r=n; int ans=0; while(l<=r) { int mid=(l+r)>>1; if(check(n,mid,cc)) { l=mid+1; ans=max(mid,ans); } else r=mid-1; } printf("%d\n",ans); } }
相关文章推荐
- 编译出现莫名其妙错误的原因
- C#执行存储过程以及传参获取返回值
- 判断 iframe 是否加载完成的完美方法
- 黑马程序员--OC封装
- SQLite学习笔记(16)-B-tree(2)
- 这才叫利用人,不要被傻傻地被利用
- Linux程序编译速度提高方法
- 用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序(约瑟夫环问题)
- Codeforces #207 div2 C. Prime Number 数论 gcd
- 剑指offer整理归纳(2/2)
- scala学习之:scala的并发编程(一)
- Number of Islands
- Number Steps
- 工人的请愿 树形DP uva12186
- poj1009 Edge Detection
- dede默认的表
- 浮动元素的均匀分布和两端对齐
- NOIP 关押罪犯
- linux sleep用法
- HTML学习-基本概念