传送门
解析:
套路题。
首先串成一串求一下SA。
然后按照二分出的 l e n len len,根据 h e i g h t height height数组分组。
在每组里面看 k k k个串是否分别满足条件就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
cs int N=100005;
namespace SA{
char s[N];
int sa[N],rk[N],ht[N],len;
int bin[N];
inline void radix_sort(int *cs x,int *cs y,int m,int n);
inline void init();
inline bool check(int x);
}
inline void SA::radix_sort(int *cs x,int *cs y,int m,int n){
memset(bin+1,0,sizeof(int)*m);
for(int re i=1;i<=n;++i)++bin[x[i]];
for(int re i=1;i<=m;++i)bin[i]+=bin[i-1];
for(int re i=n;i;--i)sa[bin[x[y[i]]]--]=y[i];
}
inline void SA::init(){
int *x=rk,*y=ht,n=len,m=256;
for(int re i=1;i<=n;++i)x[i]=s[i],y[i]=i;
radix_sort(x,y,m,n);
for(int re i=1,cnt=0;i<=n&&cnt<n;i<<=1){
cnt=0;
for(int re j=n-i+1;j<=n;++j)y[++cnt]=j;
for(int re j=1;j<=n;++j)if(sa[j]>i)y[++cnt]=sa[j]-i;
radix_sort(x,y,m,n);
swap(x,y);
x[sa[1]]=cnt=1;
for(int re j=2;j<=n;++j)x[sa[j]]=((y[sa[j]]==y[sa[j-1]])&&(y[sa[j]+i]==y[sa[j-1]+i])?cnt:++cnt);
m=cnt;
}
for(int re i=1;i<=n;++i)rk[sa[i]]=i;
for(int re i=1,k=0,j;i<=len;ht[rk[i++]]=k)
for(k?--k:0,j=sa[rk[i]-1];s[i+k]==s[j+k];++k);
}
int be[12],k;
int l[12],id[N];
int maxn[12],minn[12];
inline bool SA::check(int x){
fill(maxn+1,maxn+k+1,0);
fill(minn+1,minn+k+1,N);
for(int re i=1;i<=len;++i){
if(ht[i]<x){
fill(maxn+1,maxn+k+1,0);
fill(minn+1,minn+k+1,N);
maxn[id[sa[i]]]=sa[i];
minn[id[sa[i]]]=sa[i];
}
else{
maxn[id[sa[i]]]=max(maxn[id[sa[i]]],sa[i]);
minn[id[sa[i]]]=min(minn[id[sa[i]]],sa[i]);
maxn[id[sa[i-1]]]=max(maxn[id[sa[i-1]]],sa[i-1]);
minn[id[sa[i-1]]]=min(minn[id[sa[i-1]]],sa[i-1]);
for(int re j=1;j<=k;++j){
if(maxn[j]-minn[j]<x)break;
if(j==k)return true;
}
}
}
return false;
}
int T;
signed main(){
scanf("%d",&T);
while(T--){
scanf("%d",&k);SA::len=0;
memset(SA::s,0,sizeof SA::s);
for(int re i=1;i<=k;++i){
SA::len++;
scanf("%s",SA::s+SA::len);
be[i]=SA::len;
SA::len+=(l[i]=strlen(SA::s+SA::len));
for(int re j=be[i];j<SA::len;++j){
id[j]=i;
}
SA::s[SA::len]='$'+i;
}
SA::init();
re int l=0,r=10000;
while(l<r){
int mid=(l+r+1)>>1;
if(SA::check(mid))l=mid;
else r=mid-1;
}
printf("%d\n",l);
}
return 0;
}