Description
 
题意就是,给你n个字符串,然后给你一些二进制,然后求二进制为1的位置他们的最长公共子串。
 
Solution
 
这就是一道SAM的裸题。  构出一颗trie,然后trie上建SAM(要用bfs来建),然后每个节点标记一个二进制,最后每个fail树上的父亲把儿子的标记全部or起来。  然后把这个二进制状态更新到子集上,如果
  
   3n
  枚举子集会超时,随意要1位位的往下转移
  
   2nn
  
 
Code
 
using namespace std;
const 
int maxn=
1e6+
7;
int i,j,k,l,n,
m,ans,len,tot,
x,op;
int num,a[maxn],f[maxn];
int p,np,
q,nq,w[maxn
*3],er[
21],b[maxn
*3],c[maxn
*3],da,e[maxn
*3];
int d[maxn
*2];
int tr[maxn
*2][
26];
char 
s[maxn],st[maxn];
struct node{
    
int fa,len,son[
26],w;
}t[maxn
*2];
int extend(
int x,
int last,
int u){
    t[np=++num].len=t[p=
last].len+
1;t[np].w=u;
    
while(p&&!t[p].son[
x])t[p].son[
x]=np,p=t[p].fa;
    
if(!p)t[np].fa=
1;
    
else{
        
q=t[p].son[
x];
        
if(t[
q].len==t[p].len+
1)t[np].fa=
q;
        
else{
            t[nq=++num]=t[
q];t[nq].w=u;
            t[nq].len=t[p].len+
1;
            t[
q].fa=t[np].fa=nq;
            
while(p&&t[p].son[
x]==
q)t[p].son[
x]=nq,p=t[p].fa;
        }
    }
    
return np;
}
void bfs(){
    
int i,j,k,
x,
y;w[d[
1]=
0]=
1;
//w[
1]=extend(a[
1],d[
1]=
1);
    
for(i=j=
1;i<=j;i++){
        
x=d[i];
        fo(k,
0,
25){
            
y=
tr[
x][k];
if(!
y)
continue;
            w[d[++j]=
y]=extend(k,w[
x],b[
y]);
        }
    }
}
int main(){
    freopen(
"wechat.in",
"r",stdin);
    freopen(
"wechat.out",
"w",stdout);
    er[
0]=
1;fo(i,
1,
20)er[i]=er[i-
1]
*2;
    scanf(
"%d",&n);tot=
1;
    fo(i,
1,n){
        scanf(
"%s",st+
1);len=strlen(st+
1);
m=
0;da=max(da,len);st[++len]=
'<';
        fo(j,
1,len)
if(st[j]==
'<'){
            
if(st[j-
1]!=
'<'){
                
x=
0;
                fo(k,
1,
m){
                    
if(d[k])
x=d[k];
                    
else{
                        
if(!
tr[
x][
s[k]-
'a'])
tr[
x][
s[k]-
'a']=++op;
                        
x=
tr[
x][
s[k]-
'a'];b[
x]|=er[i-
1];
                    }
                    d[k]=
x;
                }
            }
            d[
m]=
0;--
m;
        }
else s[++
m]=st[j],d[
m]=
0;
        fo(j,
1,len)d[j]=
0;
    }
    num=
1;
    bfs();
    fo(i,
1,num)c[t[i].len]++;
    fo(i,
1,da)c[i]+=c[i-
1];
    fod(i,num,
1)e[c[t[i].len]--]=i;
    fod(i,num,
1)
x=e[i],t[t[
x].fa].w|=t[
x].w;
    fo(i,
1,num)
x=e[i],f[t[
x].w]=(f[t[
x].w]<t[
x].len)?t[
x].len:f[t[
x].w];
    fod(i,er[n]-
1,
1){
        fo(j,
1,n){
            
if(i&er[j-
1])f[i-er[j-
1]]=(f[i-er[j-
1]]<f[i])?f[i]:f[i-er[j-
1]];
        }
    }
    
for(scanf(
"%d",&
m);
m;
m--){
        scanf(
"%s",
s+
1);k=
0;
        fo(i,
1,n)
if(
s[i]==
'1')k+=er[i-
1];
        
printf(
"%d\n",f[k]);
    }
}