题解:
对于每个串,在Trie树上找到他’?’处填0或者1的位置。 那么他的子树中(不包括他)的所有串不能选。 对于他这个节点我们记录一个前缀后缀就可以做到
O(n)
O
(
n
)
了。
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+50;
typedef pair <int,int> pii;
int n; string s[N/2];
int son[N][2],any[N/2],tot=1,cnt=0;
pii pos[N/2][2];
int u[N/2][2],v[N][2];
vector <int> cont[N];
vector <int> pre[N][2];
vector <int> suf[N][2];
int dfn[N*5],ind,g[N*5],nt[N*10],vt[N*10],st[N*5],top,ins[N*5],low[N*5],id[N*5],ec,scc;
inline void add(int x,int y) {nt[++ec]=g[x]; g[x]=ec; vt[ec]=y;}
inline void addbi(int x,int y) {add(x,y); add(y,x);}
inline int find_(string &t,int p=0) {
for(;p<t.length();++p) if(t[p]=='?') break;
return p;
}
inline pii inc(int id,string &t) {
int p=1;
for(int i=0;i<t.length();i++) {
int c=t[i]-'0';
if(!son[p][c]) son[p][c]=++tot;
p=son[p][c];
}
cont[p].push_back(id);
return pii(p,cont[p].size()-1);
}
inline void build_graph() {
for(int i=1;i<=n;i++) u[i][0]=++cnt, u[i][1]=++cnt;
for(int i=1;i<=tot;i++) v[i][0]=++cnt, v[i][1]=++cnt;
for(int i=1;i<=tot;i++) {
pre[i][0].resize(cont[i].size());
pre[i][1].resize(cont[i].size());
suf[i][0].resize(cont[i].size());
suf[i][1].resize(cont[i].size());
for(int j=0;j<cont[i].size();++j)
pre[i][0][j]=++cnt, pre[i][1][j]=++cnt,
suf[i][0][j]=++cnt, suf[i][1][j]=++cnt;
}
for(int i=1;i<=tot;i++) {
for(int j=0;j<=1;j++) if(son[i][j]) {
int t=son[i][j];
add(v[i][0],v[t][0]);
add(v[t][1],v[i][1]);
}
for(int j=0;j<cont[i].size();++j) {
int o=cont[i][j]; if(o>n) o-=n;
int t1=u[o][0], t2=u[o][1];
if(cont[i][j]>n) swap(t1,t2);
if(j>0) add(pre[i][0][j],pre[i][0][j-1]);
add(pre[i][0][j],t2);
if(j>0) add(pre[i][1][j-1],pre[i][1][j]);
add(t1,pre[i][1][j]);
if(j<cont[i].size()-1) add(suf[i][0][j],suf[i][0][j+1]);
add(suf[i][0][j],t2);
if(j<cont[i].size()-1) add(suf[i][1][j+1],suf[i][1][j]);
add(t1,suf[i][1][j]);
if(j==0) {
addbi(v[i][1],suf[i][1][j]);
addbi(v[i][0],suf[i][0][j]);
}
if(j==cont[i].size()-1) {
addbi(v[i][1],pre[i][1][j]);
addbi(v[i][0],pre[i][0][j]);
}
}
}
for(int i=1;i<=n;i++) {
int p1=pos[i][0].first, p2=pos[i][0].second;
for(int j=0;j<=1;j++) if(son[p1][j]) {
add(u[i][0],v[son[p1][j]][0]);
add(v[son[p1][j]][1],u[i][1]);
}
if(p2)
add(u[i][0],pre[p1][0][p2-1]),
add(pre[p1][1][p2-1],u[i][1]);
if(p2<cont[p1].size()-1)
add(u[i][0],suf[p1][0][p2+1]),
add(suf[p1][1][p2+1],u[i][1]);
p1=pos[i][1].first, p2=pos[i][1].second;
if(p1) {
for(int j=0;j<=1;j++) if(son[p1][j]) {
add(u[i][1],v[son[p1][j]][0]);
add(v[son[p1][j]][1],u[i][0]);
}
if(p2)
add(u[i][1],pre[p1][0][p2-1]),
add(pre[p1][1][p2-1],u[i][0]);
if(p2<cont[p1].size()-1)
add(u[i][1],suf[p1][0][p2+1]),
add(suf[p1][1][p2+1],u[i][0]);
} else add(u[i][1],u[i][0]);
}
}
inline void dfs(int x) {
dfn[x]=low[x]=++ind;
st[++top]=x; ins[x]=1;
for(int e=g[x];e;e=nt[e]) {
if(!dfn[vt[e]]) dfs(vt[e]), low[x]=min(low[x],low[vt[e]]);
else if(ins[vt[e]]) low[x]=min(low[x],dfn[vt[e]]);
}
if(low[x]==dfn[x]) {
int u; ++scc; do {
ins[u=st[top--]]=0;
id[u]=scc;
} while(u!=x);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin>>n;
for(int i=1;i<=n;i++) {
cin>>s[i];
int t=find_(s[i]); any[i]=t;
if(t==s[i].length()) pos[i][0]=inc(i,s[i]);
else {
s[i][t]='0'; pos[i][0]=inc(i,s[i]);
s[i][t]='1'; pos[i][1]=inc(i+n,s[i]);
s[i][any[i]]='?';
}
}
build_graph();
for(int i=1;i<=cnt;i++) if(!dfn[i]) dfs(i);
for(int i=1;i<=n;i++) {
if(id[u[i][0]]==id[u[i][1]]) {puts("NO"); return 0;}
if(id[u[i][0]]<id[u[i][1]]) {
if(any[i]<s[i].length())
s[i][any[i]]='0';
} else s[i][any[i]]='1';
}
cout<<"YES"<<'\n';
// for(int i=1;i<=n;i++) cout<<s[i]<<'\n';
}