POJ1226 Substrings
后缀数组。
求多个字符串翻转与否中最长公共子串长。
二分答案,反过来多建一倍的字符串,二分时特判一下即可。
By:大奕哥
1 #include<cstring> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<iostream> 6 #define rank fank 7 using namespace std; 8 const int N=1000005; 9 int r[N],wa[N],wb[N],wv[N],wu[N],sa[N],rank[N],height[N],bel[N],cnt; 10 int cmp(int *r,int a,int b,int l) 11 { 12 return r[a]==r[b]&&r[a+l]==r[b+l]; 13 } 14 void da(int *r,int *sa,int n,int m) 15 { 16 int i,j,p;int *x=wa,*y=wb; 17 for(i=0;i<m;++i)wu[i]=0; 18 for(i=0;i<n;++i)wu[x[i]=r[i]]++; 19 for(i=1;i<m;++i)wu[i]+=wu[i-1]; 20 for(i=n-1;i>=0;--i)sa[--wu[x[i]]]=i; 21 for(j=1,p=1;p<n;j<<=1,m=p) 22 { 23 for(p=0,i=n-j;i<n;++i)y[p++]=i; 24 for(i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j; 25 for(i=0;i<n;++i)wv[i]=x[y[i]]; 26 for(i=0;i<m;++i)wu[i]=0; 27 for(i=0;i<n;++i)wu[wv[i]]++; 28 for(i=0;i<m;++i)wu[i]+=wu[i-1]; 29 for(i=n-1;i>=0;--i)sa[--wu[wv[i]]]=y[i]; 30 for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;++i) 31 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 32 } 33 return; 34 } 35 void calcHeight(int *rank,int *sa,int n) 36 { 37 int i,j,k=0; 38 for(i=1;i<=n;++i)rank[sa[i]]=i; 39 for(i=0;i<n;height[rank[i++]]=k) 40 for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];++k); 41 return ; 42 } 43 char s[1005]; 44 bool v[1005]; 45 int tot,num; 46 bool check(int x,int n) 47 { 48 cnt=0;memset(v,0,sizeof(v)); 49 for(int i=1;i<=n;++i) 50 { 51 if(height[i]<x){cnt=0;memset(v,0,sizeof(v));} 52 else 53 { 54 if(v[bel[sa[i-1]]]==0)cnt++,v[bel[sa[i-1]]]=1; 55 if(!v[bel[sa[i]]])cnt++,v[bel[sa[i]]]=1; 56 if(cnt>=num)return 1; 57 } 58 } 59 return 0; 60 } 61 int main() 62 { 63 int t; 64 scanf("%d",&t); 65 while(t--) 66 { 67 scanf("%d",&num); 68 int len=0;int p=0; 69 for(int i=0;i<num;++i) 70 { 71 scanf("%s",s); 72 int n=strlen(s); 73 for(int j=0;j<n;++j) 74 { 75 r[len]=s[j];bel[len]=i;++len; 76 } 77 r[len]=200+p;bel[len]=200+p;++len;++p; 78 for(int j=n-1;j>=0;--j) 79 { 80 r[len]=s[j];bel[len]=i;++len; 81 } 82 r[len]=200+p;bel[len]=200+p;++len;++p; 83 } 84 --len;r[len]=0; 85 da(r,sa,len+1,1000); 86 calcHeight(rank,sa,len); 87 int ans=0,l=1,r=len; 88 while(l<=r) 89 { 90 int mid=l+r>>1; 91 if(check(mid,len))ans=mid,l=mid+1; 92 else r=mid-1; 93 } 94 printf("%d\n",ans); 95 } 96 return 0; 97 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。