嗯,根据(nekko)大佬的说法跑去搞(SAM)建后缀树,然后发现(Trie)就过了
每个串最多有一个模糊字符,且只能是(0/1),那么考虑(2-sat)
我们发现如果把所有字符串建成一颗(Trie),那么就可以前缀优化建图,因为每个点的祖先都是自己的一个前缀
当然后缀树也可以做到,不过没必要
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define y1 qwq
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=3e6+10,inf=1<<30;
int n,m,siz;
char s[N];
int p[N],pre[N],f[N];
int head[N],cnt;
struct point
{
int nxt,to;
point(){}
point(const int &nxt,const int &to):nxt(nxt),to(to){}
}a[N<<2];
inline void link(int x,int y)
{
a[++cnt]=(point){head[x],y};head[x]=cnt;
}
struct Tire
{
vector<int> v[N];
int rt=1,sum=0,tot=1,son[N][2];
inline void insert(int n,int id)
{
int x=rt;
for(int i=1;i<=n;++i)
{
int k=s[i]-'0';
if(!son[x][k]) son[x][k]=++tot;
x=son[x][k];
}
v[x].push_back(id);
}
inline void dfs(int x)
{
int len=v[x].size();
for(int i=0;i<len;++i)
{
p[++sum]=v[x][i];
pre[p[sum]]=++siz;
f[pre[p[sum]]]=++siz;
f[siz]=pre[p[sum]];
//p 选了 fp没选
//pre 选了 fpre没选
link(p[sum],pre[p[sum]]);
//这个选了,这个及之前选了
link(f[pre[p[sum]]],f[p[sum]]);
//这个及之前不选,这个不选
if(sum!=1)
{
link(pre[p[sum-1]],pre[p[sum]]);
//上一个之前选了,这个及之前选了
link(f[pre[p[sum]]],f[pre[p[sum-1]]]);
//这个及之前不选,上一个之前不选
link(pre[p[sum-1]],f[p[sum]]);
//上一个及之前选了,这个不选
link(p[sum],f[pre[p[sum-1]]]);
//选这个,上一个及之前不选
}
}
if(son[x][0]) dfs(son[x][0]);
if(son[x][1]) dfs(son[x][1]);
sum-=len;
}
}T;
int dfn[N],low[N],st[N],col[N];
int idx,top,num;
inline void tarjan(int now)
{
dfn[now]=low[now]=++idx;
st[++top]=now;
for(int i=head[now];i;i=a[i].nxt)
{
int t=a[i].to;
if(!dfn[t])
{
tarjan(t);
low[now]=min(low[now],low[t]);
}
else if(!col[t]) low[now]=min(low[now],dfn[t]);
}
if(dfn[now]==low[now])
{
col[now]=++num;
while(st[top]!=now) col[st[top--]]=num;
--top;
}
}
inline void main()
{
n=read();siz=n;
for(int i=1;i<=n;++i)
{
scanf("%s",s+1);
int k=0,len=strlen(s+1);
for(int j=1;j<=len;++j) if(s[j]=='?') k=j;
f[i]=++siz;f[siz]=i;
if(k)
{
s[k]='0';T.insert(len,f[i]);
s[k]='1';T.insert(len,i);
}
else link(f[i],i),T.insert(len,i);
}
T.dfs(T.rt);
for(int i=1;i<=siz;++i)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=siz;++i)
if(col[i]==col[f[i]]) return(void)puts("NO");
puts("YES");
}
}
signed main()
{
//freopen("haha.in","r",stdin);
red::main();
return 0;
}