给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
标签:pac ext 整数 mem using pre zoj oid 公共子串
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 10050 int ws[N],wa[N],wb[N],wv[N],r[N],sa[N],height[N],rank[N],n,m,T,pos[N],h[10]; char str[N]; void build_suffix_array() { m=T+27; int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=r[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; for(p=j=1;p<n;j<<=1,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]-j>=0) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; for(t=x,x=y,y=t,x[sa[0]]=0,i=p=1;i<n;i++) { if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1; else x[sa[i]]=p++; } } for(i=1;i<n;i++) rank[sa[i]]=i; for(i=p=0;i<n-1;height[rank[i++]]=p) for(p?p--:0,j=sa[rank[i]-1];r[i+p]==r[j+p];p++) ; } bool full() { int i; for(i=1;i<=T;i++) if(!h[i]) return 0; return 1; } bool check(int x) { int i,j; for(i=1;i<n;i++) { if(height[i]<x) { memset(h,0,sizeof(h)); } h[pos[sa[i]]]++; if(full()) return 1; } return 0; } int main() { scanf("%d",&T); int i,j; for(i=1;i<=T;i++) { scanf("%s",str); for(j=0;str[j];j++) r[n]=str[j]-‘a‘+1,pos[n++]=i; r[n++]=26+i; } n++; build_suffix_array(); int l=0,ri=n+1; while(l<ri) { int mid=(l+ri)>>1; if(check(mid)) l=mid+1; else ri=mid; } printf("%d\n",l-1); }
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
标签:pac ext 整数 mem using pre zoj oid 公共子串
原文地址:https://www.cnblogs.com/suika/p/8996194.html