/**//* 【题目】给你N个字符串,输出若干个子串,满足大于N/2个字符串含有它。 【分析】先将N个字符串并成一个字符串,中间用不同的符号分割开。 然后利用后缀数组求出Height数组,二分枚举答案X,将Height分为若干组(如何分组? 若Height[I]大于等于X,则属于上一组,否则属于新的一组), 若某个组里面的后缀的来源是大于N/2个字符串的,则可行,继续放大X, 否则缩小X。若最后X=0则No Answer,否则再次分组,输出满足条件的组的前缀。 */ #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<string> using namespace std; #define maxn 100000+105 char s[maxn]; int sa[maxn],h[maxn],height[maxn],rank[maxn]; int k,n; int maxlen; int m; int belong[maxn]; set<string>outset; bool cmp1(const int & a,const int & b) { return (s[a]<s[b]); } bool cmp2(const int & a,const int & b) { return (rank[a]<rank[b] || (rank[a]==rank[b]&& (a+k<n?rank[a+k]:-1)<(b+k<n?rank[b+k]:-1))); } void suffixArray() { int i,j; for(i=0;i<n;i++) sa[i]=i; sort(sa,sa+n,cmp1); for(i=0;i<n;i++) { if(i==0||s[sa[i]]!=s[sa[i-1]]) rank[sa[i]]=i; else rank[sa[i]]=rank[sa[i-1]]; } for(k=1;k<n;k*=2) { sort(sa,sa+n,cmp2); for(i=0;i<n;i++) { if( i==0 || (cmp2(sa[i],sa[i-1])||cmp2(sa[i-1],sa[i])) ) h[sa[i]]=i; else h[sa[i]]=h[sa[i-1]]; } memcpy(rank, h, n * sizeof(int)); }
height[0] = 0; for(i = 0, j = 0; i < n; i++) { if(rank[i]>0) { while(s[sa[rank[i] - 1] + j] == s[i + j]) j++; height[rank[i]] = j; if(j > 0) j--; } } } bool ok(int len) { int count=0; bool visit[105]={0}; for(int i=1;i<n;i++) { if(height[i]<len) { if(count>0) { count=0; memset(visit,0,sizeof(visit)); } } else { if(!visit[belong[sa[i-1]]]) { visit[belong[sa[i-1]]]=1; count++; } if(!visit[belong[sa[i]]]) { visit[belong[sa[i]]]=1; count++; } //if(count>=ceil((double)m/2)) if(count>m/2) return 1; } } return 0; } int binarySearch() { int l=0,r=maxlen; int mid; while(l<r) { mid=(l+r+1)>>1; if(ok(mid)) l=mid; else r=mid-1; } return l; } void search(int len) { outset.clear(); bool visit[105]={0}; int count=0; for(int i=1;i<n;i++) { if(height[i]<len) { if(count>0) { if(count>m/2) { for(int j=0,index=sa[i-1];j<len;j++) putchar(s[j+index]); putchar('\n'); } count=0; memset(visit,0,sizeof(visit)); } } else { if(!visit[belong[sa[i-1]]]) { visit[belong[sa[i-1]]]=1; count++; } if(!visit[belong[sa[i]]]) { visit[belong[sa[i]]]=1; count++; } } } } int main() { int tmp,j,ans; bool first=1; while(scanf("%d", &m)!=EOF&&m) { if(!first) { printf("\n"); } else first=0;
n=0; maxlen=0; for(int i=0;i<m;i++) { scanf("%s",s+n); for(j=n;s[j];j++) belong[j]=i;
tmp=j-n; if(tmp>maxlen) maxlen=tmp; n+=tmp; s[n++]='z'+i+1; } //s[n]='$'; suffixArray(); ans=binarySearch(); if(!ans) printf("?\n"); else search(ans); } return 0; }
|