首页 > 代码库 > poj 3261 二分答案+后缀数组 求至少出现k次的最长重复子序列
poj 3261 二分答案+后缀数组 求至少出现k次的最长重复子序列
1 #include "stdio.h" 2 #define maxn 20010 3 4 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; 5 int rank[maxn],height[maxn]; 6 int r[maxn],sa[maxn],ans[maxn]; 7 int n,res,k; 8 9 int cmp(int *r,int a,int b,int l)10 {11 return r[a]==r[b]&&r[a+l]==r[b+l];12 }13 14 void da(int *r,int *sa,int n,int m)15 {16 int i,j,p,*x=wa,*y=wb,*t;17 for(i=0; i<m; i++) ws[i]=0;18 for(i=0; i<n; i++) ws[x[i]=r[i]]++;19 for(i=1; i<m; i++) ws[i]+=ws[i-1];20 for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;21 for(j=1,p=1; p<n; j*=2,m=p)22 {23 24 for(p=0,i=n-j; i<n; i++) y[p++]=i;25 for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;26 for(i=0; i<n; i++) wv[i]=x[y[i]];27 for(i=0; i<m; i++) ws[i]=0;28 for(i=0; i<n; i++) ws[wv[i]]++;29 for(i=1; i<m; i++) ws[i]+=ws[i-1];30 for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];31 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)32 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;33 }34 return;35 }36 37 void calheight(int *r,int *sa,int n)38 {39 int i,j,k=0;40 for(i=1; i<=n; i++) rank[sa[i]]=i;41 for(i=0; i<n; height[rank[i++]]=k)42 for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);43 return;44 }45 46 bool calc(int x) //x:length47 {48 int rec[maxn];49 int nm=0;50 for (int i=1;i<=n;i++)51 {52 if (height[i]<x)53 {54 nm++;55 rec[nm]=i;56 }57 }58 nm++; rec[nm]=n+1;59 for (int i=1;i<=nm;i++)60 {61 int tl=rec[i-1],tr=rec[i];62 if (tr-tl>=k) return true;63 }64 return false;65 }66 67 int main()68 {69 scanf("%d %d",&n,&k);70 for (int i=0; i<n; i++)71 scanf("%d",&r[i]);72 r[n]=0;73 74 da(r,sa,n+1,200);75 calheight(r,sa,n);76 77 //TODO: Please Code Here78 int l=0,r=n,res=0;79 while (r>=l)80 {81 int mid=(l+r)/2;82 if (calc(mid))83 {84 if (mid>res) res=mid;85 l=mid+1;86 }87 else88 r=mid-1;89 }90 printf("%d\n",res);91 return 0;92 }
poj 3261 二分答案+后缀数组 求至少出现k次的最长重复子序列
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。