求在≥k个串中出现过的最长子串.还是先都连起来,用特殊字符隔开,然后二分答案,按h分组,在一组内统计出现过的子串,满足条件就更新,注意可能有多个子串满足条件,按照顺序存下来就好了。大坑点见注释。(有人就拿char过了,很神。)
#include <cstdio>
#include <cstring>
#define N 102000
int s[N];
bool blank=0,vis[110];
int belong[N],n,k,ans[N];
int count[N],rank[N<<1],rank1[N],sa[N],tmp[N],h[N];
inline int max(int x,int y){return x>y?x:y;}
inline bool jud(int x){
memset(vis,0,sizeof(vis));
int num=0,cnt=0;
for(int i=1;i<=n+1;++i){
if(h[i]>=x){
if(!vis[belong[sa[i]]]) vis[belong[sa[i]]]=1,cnt++;
if(!vis[belong[sa[i-1]]]) vis[belong[sa[i-1]]]=1,cnt++;
}
else{
if(cnt>k/2) ans[++num]=sa[i-1];
cnt=0;memset(vis,0,sizeof(vis));
}
}
if(num){ans[0]=num;return 1;}
else return 0;
}
int main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
while(1){
n=0;int r=0;char str[1010];
scanf("%d",&k);if(!k) break;
for(int i=1;i<=k;++i){
//一定要转成int去做,char实在是伤不起啊。。
//char 8字节,最高位符号位,所以当数值>127时就会变负的啊!
//以后再也不要用char做了。。
scanf("%s",str+1);int len=strlen(str+1);r=max(r,len);
for(int j=1;j<=len;++j) s[++n]=str[j]-'a'+1,belong[n]=i;
s[++n]=100+i;belong[n]=i;
}
memset(count,0,sizeof(count));
memset(rank,0,sizeof(rank));
memset(h,0,sizeof(h));
for(int i=1;i<=n;++i) count[s[i]]=1;
for(int i=1;i<=200;++i) count[i]+=count[i-1];
for(int i=n;i>=1;--i) rank[i]=count[s[i]];
int kk=0;
for(int p=1;kk!=n;p<<=1){
memset(count,0,sizeof(count));
for(int i=1;i<=n;++i) count[rank[i+p]]++;
for(int i=1;i<=n;++i) count[i]+=count[i-1];
for(int i=n;i>=1;--i) tmp[count[rank[i+p]]--]=i;
memset(count,0,sizeof(count));
for(int i=1;i<=n;++i) count[rank[tmp[i]]]++;
for(int i=1;i<=n;++i) count[i]+=count[i-1];
for(int i=n;i>=1;--i) sa[count[rank[tmp[i]]]--]=tmp[i];
memcpy(rank1,rank,sizeof(rank1));
rank[sa[1]]=kk=1;
for(int i=2;i<=n;++i){
if(rank1[sa[i]]!=rank1[sa[i-1]]||rank1[sa[i]+p]!=rank1[sa[i-1]+p]) ++kk;
rank[sa[i]]=kk;
}
}kk=0;
for(int i=1;i<=n;++i){
if(rank[i]==1){h[1]=0;continue;}
if(i==1||h[rank[i-1]]<=1) kk=0;
if(kk) --kk;
while(s[i+kk]==s[sa[rank[i]-1]+kk]) ++kk;
h[rank[i]]=kk;
}
int l=1;
while(l<=r){
int mid=(l+r)>>1;
if(jud(mid)) l=mid+1;
else r=mid-1;
}
if(blank) puts("");
else blank=1;
if(l==1) puts("?");
else for(int i=1;i<=ans[0];++i){
for(int j=0;j<l-1;++j) putchar(s[ans[i]+j]+'a'-1);
puts("");
}
}
return 0;
}