POJ 3261 浅谈后缀数组HEIGHT数组的实际应用
2017-07-31 09:41
633 查看
世界真的很大
后缀数组是个神奇东西,应用也挺多的
后缀排名这个东西很有用
这又是一道奶牛题
POJ昨天卡了害得我测了好久
看题先:
description:
给定一个长为n(1≤n≤105 )的字符串,求其最长的至少出现了k次的 可重叠子串长度。
input
第一行两个整数n,k,接下来n个整数表示序列(字符串)
output
一个整数表示答案
看到求最长什么的应该想到二分,再考虑一下是不是具有二分的性质。
如果一个串出现了k次,那么长度比其小的串肯定至少出现了k次,这是显然的
那么就可以二分了,二分一个长度,每次check看有没有这个长度的字串出现了k次及以上
考虑怎么check,后缀数组中的后缀排名,如果几个后缀有一部分公共前缀,那么在后缀排名上他们一定是挨在一起的,因为后缀排名比较的是字典序,由于这几个后缀前几个字符都是相同的,所以字典序上他们必然是挨在一起的。
我们可以利用这个性质,把后缀排名里面,挨在一起的,有公共前缀长度大于二分的值的,分为一组,这一组里满足有长度大于二分值的公共字串,再检查组内是不是有超过k个后缀,就是这个公共字串有没有出现大于等于k次
完整代码:
#include<stdio.h> #include<algorithm> using namespace std; int n,k,big=0; int wa[100010],wb[100010],wv[100010],ws[100010]; int rank[100010],height[100010]; int sa[100010],r[100010]; bool cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void calheight(int *r,int *sa,int n) { int k=0,j; for(int i=1;i<=n;i++) rank[sa[i]]=i; for(int i=0;i<n;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); } void da(int *r,int *sa,int n,int m) { int *x=wa,*y=wb,*t; for(int i=0;i<m;i++) ws[i]=0; for(int i=0;i<n;i++) ws[x[i]=r[i]]++; for(int i=1;i<m;i++) ws[i]+=ws[i-1]; for(int i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; for(int p=1,j=1;p<n;j<<=1,m=p) { p=0; for(int i=n-j;i<n;i++) y[p++]=i; for(int i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(int i=0;i<n;i++) wv[i]=x[y[i]]; for(int i=0;i<m;i++) ws[i]=0; for(int i=0;i<n;i++) ws[wv[i]]++; for(int i=1;i<m;i++) ws[i]+=ws[i-1]; for(int i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; int 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++; } } bool check(int mid) { int tmp=0; for(int i=2;i<=n;i++) { if(height[i]>=mid) tmp++; if(tmp>=k) return 1; if(height[i]<mid) tmp=1; } return false ; } int main() { scanf("%d%d",&n,&k); for(int i=0;i<n;i++) scanf("%d",&r[i]),big=max(big,r[i]); da(r,sa,n+1,big+1); calheight(r,sa,n); int lf=1,rg=n,ans=0; while(lf<=rg) { int mid=(lf+rg)>>1; if(check(mid)) ans=mid,lf=mid+1; else rg=mid-1; } printf("%d\n",ans); return 0; } /* Whoso pulleth out this sword from this stone and anvil is duly born King of all England */
嗯,就是这样
相关文章推荐
- 后缀数组(二)利用height对sa数组分组的做法(poj 1743 & poj 3261 )
- poj 2406 Power Strings (kmp 中 next 数组的应用||后缀数组)
- poj 3261 后缀数组
- 泛型--浅谈在实际中的应用一
- POJ 3261 (后缀数组 二分) Milk Patterns
- POJ 3261(后缀数组)
- POJ 3261 Milk Patterns(后缀数组+二分答案+离散化)
- 浅谈PHP 闭包特性在实际应用中的问题
- poj 3261 后缀数组 可重叠的 k 次最长重复子串
- Poj 3261 Milk Patterns(后缀数组+二分答案)
- 浅谈iOS调试技巧的实际应用 UI篇
- POJ 2406 KMP next数组的应用
- 【next数组应用】POJ 2406 Power Strings
- 后缀数组 Milk Patterns POJ - 3261
- poj 3261 Milk Patterns 最长的出现最少k次的重复(可重叠)子串 后缀数组
- POJ 2752: S 4000 eek the Name, Seek the Fame(简单KMP-NEXT数组的应用)
- 【后缀数组求可重叠的k 次最长重复子串】POJ 3261
- 浅谈实际开发中数据源在JDBC中的应用
- poj 3261 Milk Patterns(后缀数组)
- poj 1961 Period 【KMP-next前缀数组的应用】