P6965 [NEERC2016] Binary Code
*P6965 [NEERC2016] Binary Code
一个字符串至多含有一个问号,所以状态至多有两种,考虑 2-SAT,设
容易发现,若字符串
刻画前缀关系的结构是字典树。对于若
我们还要处理
综上,点数和边数关于
#include <bits/stdc++.h>
using namespace std;
#define TIME 1e3 * clock() / CLOCKS_PER_SEC
using ll = long long;
using pii = pair<int, int>;
bool Mbe;
constexpr int N = 3e6 + 5;
int n, node, trie, son[N][2], fa[N], ed[N], pos[N], qm[N];
vector<int> e[N], buc[N], pref[N], suff[N];
string s[N];
void insert(int id, string s) {
int p = n * 2;
for(char it : s) {
if(!son[p][it - '0']) {
e[p].push_back(trie), e[trie ^ 1].push_back(p ^ 1);
fa[son[p][it - '0'] = trie] = p, trie += 2;
}
p = son[p][it - '0'];
}
ed[id] = p, pos[id] = buc[p].size();
buc[p].push_back(id ^ 1);
e[p].push_back(id ^ 1), e[p ^ 1].push_back(id ^ 1);
}
int dfn[N], dn, low[N], vis[N], col[N], cn, stc[N], top;
void tarjan(int id) {
dfn[id] = low[id] = ++dn, stc[++top] = id, vis[id] = 1;
for(int it : e[id]) {
if(!dfn[it]) tarjan(it), low[id] = min(low[id], low[it]);
else if(vis[it]) low[id] = min(low[id], dfn[it]);
}
if(low[id] == dfn[id]) {
col[id] = ++cn;
while(stc[top] != id) col[stc[top]] = cn, vis[stc[top--]] = 0;
vis[stc[top--]] = 0;
}
}
bool Med;
int main() {
fprintf(stderr, "%.3lf MB\n", (&Mbe - &Med) / 1048576.0);
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n, trie = n * 2 + 2;
for(int i = 0; i < n; i++) {
cin >> s[i], qm[i] = s[i].find('?');
if(qm[i] == -1) insert(i * 2, s[i]), insert(i * 2 + 1, s[i]);
else s[i][qm[i]] = '0', insert(i * 2, s[i]), s[i][qm[i]] = '1', insert(i * 2 + 1, s[i]);
}
node = trie;
for(int i = n * 2; i < trie; i += 2) {
if(buc[i].empty()) continue;
int sz = buc[i].size();
pref[i].resize(sz), suff[i].resize(sz);
for(int p = 0; p < sz; p++) {
if(p) e[node].push_back(node - 1);
e[node].push_back(buc[i][p]);
pref[i][p] = node++;
}
for(int p = sz - 1; ~p; p--) {
if(p + 1 < sz) e[node].push_back(node - 1);
e[node].push_back(buc[i][p]);
suff[i][p] = node++;
}
}
for(int i = 0; i < n * 2; i++) {
int p = ed[i];
if(son[p][0]) e[i].push_back(son[p][0]);
if(son[p][1]) e[i].push_back(son[p][1]);
e[i].push_back(fa[p] ^ 1);
int q = pos[i];
if(q) e[i].push_back(pref[p][q - 1]);
if(q + 1 < buc[p].size()) e[i].push_back(suff[p][q + 1]);
}
for(int i = 0; i < node; i++) if(!dfn[i]) tarjan(i);
for(int i = 0; i < n; i++) {
if(col[i * 2] == col[i * 2 + 1]) puts("NO"), exit(0);
if(qm[i] != -1) s[i][qm[i]] = col[i * 2] < col[i * 2 + 1] ? '0' : '1';
}
cout << "YES\n";
for(int i = 0; i < n; i++) cout << s[i] << "\n";
cerr << TIME << " ms\n";
return 0;
}