poj 3080
后缀数组,二分求多串子串,height数组山的结构。
#include<iostream> #include<fstream> using namespace std; #define N 620 int sa[N],sa1[N],rank[N],rank1[N],c[N],h[N]; char m[N]; int n,pow,count; int cmp(const void *a,const void *b){ int x=*(int*)a; int y=*(int*)b; if(rank[x]!=rank[y]) return(1); else if(rank[x+pow]!=rank[y+pow]) return(1); else return(0); } void creat(){ int i,j,k; for(i=0;i<500;i++) c[i]=0; for(i=0;i<n;i++) c[m[i]]++; for(i=1;i<500;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[m[i]]]=i; for(i=0,j=0;i<n;i++) { if(i>0&&m[sa[i]]!=m[sa[i-1]]) j++; rank[sa[i]]=j; } for(pow=1;pow<n;pow*=2) { for(i=0;i<n;i++) c[i]=0; for(i=0;i<n;i++) if(sa[i]+pow<n) c[rank[sa[i]+pow]]++; else c[rank[sa[i]]]++; for(i=1;i<n;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) if(sa[i]+pow<n) sa1[--c[rank[sa[i]+pow]]]=sa[i]; else sa1[--c[rank[sa[i]]]]=sa[i]; for(i=0;i<n;i++) c[i]=0; for(i=0;i<n;i++) c[rank[sa1[i]]]++; for(i=1;i<n;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[rank[sa1[i]]]]=sa1[i]; for(i=0,j=0;i<n;i++) { if(i>0&&cmp(&sa[i],&sa[i-1])!=0) j++; rank1[sa[i]]=j; } for(i=0;i<n;i++) rank[i]=rank1[i]; } } void height(){ int i,j,k=0; for(i=0;i<n;i++) { if(rank[i]==0) h[rank[i]]=k=0; else { if(k>0) k--; j=sa[rank[i]-1]; for(;m[i+k]==m[j+k];k++); h[rank[i]]=k; } } } int v[11]; int f[700]; int ans; int judge(int len){ int i; int sum=0; for(i=1;i<n;i++) { if(h[i]>=len) { if(v[f[sa[i-1]]]==0) { v[f[sa[i-1]]]=1; sum++; if(sum==count) { ans=sa[i-1]; return 1; } } if(v[f[sa[i]]]==0) { v[f[sa[i]]]=1; sum++; if(sum==count) { ans=sa[i]; return 1; } } } else { sum=0; memset(v,0,sizeof(v)); } } return(0); } int main(){ int i,j,k,mid; // ifstream cin("in.txt"); int K; cin>>K; while(K--){ cin>>count; n=0; for(i=1;i<=count;i++) { for(j=1;j<=60;j++) { cin>>m[n++]; f[n-1]=i; } m[n++]=count-i; } creat(); height(); i=0;j=n; while(i<=j) { mid=(i+j)/2; memset(v,0,sizeof(v)); if(judge(mid)) i=mid+1; else j=mid-1; } if(j<3) cout<<"no significant commonalities"<<endl; else { for(i=ans;i<ans+j;i++) cout<<m[i]; cout<<endl; } } return(0); }