把所有串都扔进字典树 如果有两个是祖先和子孙的关系 就不能共存 那么我们直接用字典树辅助建一下图 跑2-SAT就好了
ps. 同时一个点上只能有一个 还要用前后缀建一下图
说起来真轻松
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline int read(char *s){
char c=nc(); int len=0;
for (;!(c=='0' || c=='1' || c=='?');c=nc());
for (;c=='0' || c=='1' || c=='?';s[++len]=c,c=nc()); s[++len]=0; return len-1;
}
const int N=4000005; //
const int M=10000005; //
struct edge{
int u,v,next;
}G[M];
int head[N],inum;
inline void add(int u,int v){
int p=++inum; G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
#define V G[p].v
int pre[N],low[N],clk;
int scc[N],cnt; int Stack[N],pnt;
#define V G[p].v
inline void dfs(int u){
pre[u]=low[u]=++clk; Stack[++pnt]=u;
for (int p=head[u];p;p=G[p].next)
if (!pre[V])
dfs(V),low[u]=min(low[u],low[V]);
else if (!scc[V])
low[u]=min(low[u],pre[V]);
if (low[u]==pre[u]){
++cnt;
while (Stack[pnt]!=u) scc[Stack[pnt--]]=cnt; scc[Stack[pnt--]]=cnt;
}
}
const int ND=1000005;
int ncnt=1,rt=1;
int ch[ND][2],par[ND];
int pos[ND<<1];
inline void ins(char *s,int len,int idx){
int p=rt;
for (int i=1;i<=len;i++){
int t=s[i]=='1';
if (ch[p][t]==0) ch[p][t]=++ncnt,par[ncnt]=p;
p=ch[p][t];
}
pos[idx]=p-1;
}
vector<int> lst[ND];
int n,Tot;
int blank[ND],Ans[ND];
char S[ND<<1]; int len;
char *str[N];
int tmp[ND<<1];
inline bool cmp(int a,int b){
return pos[a]<pos[b];
}
int main(){
char *s=S;
freopen("binary.in","r",stdin);
freopen("binary.out","w",stdout);
read(n);
for (int i=0;i<n;i++){
len=read(str[i]=s);
s=str[i]+len+1;
*s='\n';
int t=0;
for (int j=1;j<=len;j++) if (str[i][j]=='?') t=j;
blank[i]=t;
if (!t){
ins(str[i],len,i<<1);
pos[i<<1|1]=pos[i<<1];
add(i<<1,i<<1|1);
}
else{
str[i][t]='0';
ins(str[i],len,i<<1);
str[i][t]='1';
ins(str[i],len,i<<1|1);
}
}
Tot=n<<1;
for (int i=1;i<=ncnt;i++)
for (int j=0;j<2;j++)
if (ch[i][j]){
add(Tot+((i-1)<<1),Tot+((ch[i][j]-1)<<1));
add(Tot+((ch[i][j]-1)<<1|1),Tot+((i-1)<<1|1));
}
for (int i=0;i<(n<<1);i++){
lst[pos[i]].push_back(i);
if (ch[pos[i]+1][0])
add(i,Tot+((ch[pos[i]+1][0]-1)<<1));
if (ch[pos[i]+1][1])
add(i,Tot+((ch[pos[i]+1][1]-1)<<1));
add(i,Tot+((par[pos[i]+1]-1)<<1|1));
add(Tot+(pos[i]<<1),i^1);
add(Tot+(pos[i]<<1|1),i^1);
}
Tot=Tot+(ncnt<<1);
for (int i=0;i<ncnt;i++)
if ((int)lst[i].size()>1){
int tmp=Tot;
for (int j=0;j<(int)lst[i].size();j++){
add(tmp+j,lst[i][j]^1);
if (j-1>=0)
add(tmp+j,tmp+j-1);
}
tmp+=(int)lst[i].size();
for (int j=0;j<(int)lst[i].size();j++){
add(tmp+j,lst[i][j]^1);
if (j+1<(int)lst[i].size())
add(tmp+j,tmp+j+1);
}
for (int j=0;j<(int)lst[i].size();j++){
if (j-1>=0)
add(lst[i][j],Tot+j-1);
if (j+1<(int)lst[i].size())
add(lst[i][j],tmp+j+1);
}
Tot+=2*(int)lst[i].size();
}
for (int i=0;i<Tot;i++)
if (!pre[i])
dfs(i);
for (int i=0;i<n;i++)
if (scc[i<<1]==scc[i<<1|1])
printf("NO\n"),exit(0);
else
Ans[i]=scc[i<<1]<scc[i<<1|1]?0:1;
for (int i=0;i<n;i++)
if (blank[i])
str[i][blank[i]]='0'+Ans[i];
printf("YES\n");
printf("%s",S+1);
return 0;
}