poj 2774 Long Long Message 题意:求两个字符串的最长公共子串、 才开始学后缀数组,拿这个题来练了下手。在求sa的过程中理解基数排序的过程,对LHQ牛的模板理解就会更深入。 感觉da的实现没必要理解得很深,主要用的还是height数组。 /* * File: main.cpp * Author: Mi * * Created on 2011年4月25日, 下午8:33 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <map> #include <vector> #include <stdlib.h> #define MAX 200005 using namespace std; /* * */ int wa[MAX],wb[MAX],ws[MAX],wv[MAX]; int r[MAX],sa[MAX]; char str[MAX]; 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++) 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=0;i<m;i++) printf("%d ",ws[i]); puts("");*/ for(i=n-1;i>=0;i--) sa[--ws[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(int k=0;k<n;k++) printf("%d ",sa[k]); puts(""); for(int k=0;k<n;k++) printf("x==%d y==%d/n",x[k],y[k]); puts("*******");*/ 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,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 height[MAX],rank[MAX]; void Callheight(int *r,int *sa,int n) { int i,j,k=0; for(i=1;i<=n;i++) rank[sa[i]]=i; for(i=0;i<n;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); return ; } int main(int argc, char** argv) { int n,m=0,l,i,ans=0; scanf("%s",str); str[l=strlen(str)]=1; scanf("%s",str+l+1); for(i=0;str[i];i++) { r[i]=str[i]; if(r[i]>m) m=r[i]; } r[i]=0; n=i; Da(r,sa,n,m+1); Callheight(r,sa,n-1); for(i=2;i<=n;i++) if(height[i]>ans) if(l>sa[i]&&l<sa[i-1]||l>sa[i-1]&&l<sa[i]) ans=height[i]; printf("%d/n",ans); // for(i=1;i<=n;i++) // printf("%d ",sa[i]); // puts(str); return 0; }