poj 3294
后缀数组,height的考察。
代码:
#include<iostream> #include<fstream> using namespace std; #define N 100200 int sa[N],sa1[N],rank[N],rank1[N],c[N],h[N]; int 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); } int cmp1(const void *a,const void *b){ return m[*((int *)a)]-m[*((int *)b)]; } void creat(){ int i,j,k; for(i=0;i<n;i++) sa[i]=i; qsort(sa,n,sizeof(int),cmp1); 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[101]; int f[100201]; int judge(int len){ int i; int sum=0; memset(v,0,sizeof(v)); for(i=1;i<n;i++) { if(h[i]>=len) { if(f[sa[i-1]]!=0&&v[f[sa[i-1]]]==0) { sum++; if(sum>count/2) return 1; v[f[sa[i-1]]]=1; } if(f[sa[i]]!=0&&v[f[sa[i]]]==0) { sum++; if(sum>count/2) return 1; v[f[sa[i]]]=1; } } else { memset(v,0,sizeof(v)); sum=0; } } return(0); } void print(int len){ int i,j; int sum=0; int find=0; memset(v,0,sizeof(v)); for(i=1;i<n;i++) { if(h[i]>=len&&!find) { if(f[sa[i-1]]!=0&&v[f[sa[i-1]]]==0) { sum++; if(sum>count/2) { find=1; for(j=sa[i-1];j<sa[i-1]+len;j++) cout<<(char)(m[j]-100); cout<<endl; } v[f[sa[i-1]]]=1; } if(f[sa[i]]!=0&&v[f[sa[i]]]==0&&!find) { sum++; if(sum>count/2) { find=1; for(j=sa[i];j<sa[i]+len;j++) cout<<(char)(m[j]-100); cout<<endl; } v[f[sa[i]]]=1; } } if(h[i]<len) { memset(v,0,sizeof(v)); sum=0; find=0; } } } int main(){ int i,j,k,mid; // ifstream cin("in.txt"); char c[1005]; while(1) { // cin>>count; scanf("%d",&count); if(count==1) { // cin>>c; scanf("%s",c); cout<<c<<endl<<endl; continue; } if(count==0) return 0; n=0; for(i=1;i<=count;i++) { // cin>>c; scanf("%s",c); for(j=0;j<strlen(c);j++) { m[n++]=c[j]+100; f[n-1]=i; } m[n++]=count-i+1; f[n-1]=0; } creat(); height(); i=0;j=n; while(i<=j) { mid=(i+j)/2; if(judge(mid)) i=mid+1; else j=mid-1; } if(j==0) cout<<'?'<<endl<<endl; else { print(j); cout<<endl; } } return(0); }