Submission #254797

#TimeUsernameProblemLanguageResultExecution timeMemory
254797model_codeViruses (BOI20_viruses)C++17
100 / 100
171 ms21624 KiB
// O(K * L^3 * log)

#include <bits/stdc++.h>

using namespace std;

const int MK = 1000, ML = 51;

namespace AhoCorasick {
	struct node {
		int next[2];
		bool leaf;
		int p;
		char pch;
		int link;
		int go[2];
	};
	
	node t[ML + 1];
	int sz;
	
	void readString() {
		int len;
		ignore = scanf("%d", &len);
		
		int v = 0;
		for (int i = 0, c; i < len; i++) {
			ignore = scanf("%d", &c);
			
			if (t[v].next[c] == -1) {
				memset(t[sz].next, -1, sizeof t[sz].next);
				memset(t[sz].go, -1, sizeof t[sz].go);
				t[sz].link = -1;
				t[sz].p = v;
				t[sz].pch = c;
				t[v].next[c] = sz++;
			}
			
			v = t[v].next[c];
		}
		
		t[v].leaf = true;
	}
	
	int go(int v, int c);
	
	int get_link(int v) {
		if (t[v].link == -1) {
			if (v == 0 || t[v].p == 0) t[v].link = 0;
			else t[v].link = go(get_link(t[v].p), t[v].pch);
		
			get_link(t[v].link);
			if (t[t[v].link].leaf) t[v].leaf = true;
		}
		
		return t[v].link;
	}

	int go(int v, int c) {
		if (t[v].go[c] == -1) {
			if (t[v].next[c] != -1) t[v].go[c] = t[v].next[c];
			else t[v].go[c] = v == 0 ? 0 : go(get_link(v), c);
		}
		
		return t[v].go[c];
	}
	
	int to[ML][2];
	int create(int m) {
		t[0].p = t[0].link = -1;
		memset(t[0].next, -1, sizeof t[0].next);
		memset(t[0].go, -1, sizeof t[0].go);
		sz = 1;
		
		for (int i = 0; i < m; i++) readString();
		
		int cnt = 0;
		map<int, int> mp;
		for (int i = 0; i < sz; i++) {
			get_link(i);
			if (t[i].leaf) continue;
			
			mp[i] = cnt++;
		}
		
		for (auto p : mp) {
			int v = p.first;
			for (int c = 0; c < 2; c++) {
				int u = go(v, c);
				if (t[u].leaf) to[p.second][c] = -1;
				else to[p.second][c] = mp[u];
			}
		}
		
		return cnt;
	}
}

typedef unsigned long long ull;

struct Int {
	static const ull INF;
	
	ull x;
	
	Int(ull x = INF) : x(x) { }
	
	Int operator + (const Int& rhs) const {
		if (x == INF || rhs.x == INF) return INF;
		
		return min(x + rhs.x, INF);
	}
	
	bool operator < (const Int& rhs) const {
		if (x == INF) return false;
		if (rhs.x == INF) return true;
		return x < rhs.x;
	}
};

const ull Int::INF = 1ULL << 63;

int a[MK], b[3 * MK], firstB[MK], lastB[MK];
vector<int> mutations[MK];

void simplifyMutations(int& n, int g) {
	int it = lastB[n - 1];
	
	for (int i = 0; i < n; i++) {
		int k = lastB[i] - firstB[i];
		if (k <= 2) continue;
		
		a[n] = g;
		firstB[n] = firstB[i];
		lastB[n] = lastB[i] - 1;
		
		firstB[i] = it;
		b[it++] = g;
		b[it++] = b[lastB[i] - 1];
		lastB[i] = it;
		
		g++;
		n++;
	}
	
	for (int i = 0; i < n; i++) {
		for (int j = firstB[i]; j < lastB[i]; j++) {
			mutations[b[j]].push_back(i);
		}
	}
}

int L;
Int dp[MK][ML][ML];
set<tuple<ull, int, int, int>> S;

void update(int f, int s, int e, const Int& val) {
	if (val < dp[f][s][e]) {
		if (dp[f][s][e].x != Int::INF) {
			S.erase(make_tuple(dp[f][s][e].x, f, s, e));
		}
		
		dp[f][s][e] = val;
		
		S.emplace(val.x, f, s, e);
	}
}

void recalcMutationFast(int mut, int f, int s, int e) {
	int x = a[mut];
	int y = b[firstB[mut]];

	int k = lastB[mut] - firstB[mut];
	if (k == 1) {
		update(x, s, e, dp[y][s][e]);
		
		return;
	}
	
	assert(k == 2);
	
	int z = b[firstB[mut] + 1];
	
	if (y == f) {
		for (int t = 0; t < L; t++) {
			update(x, s, t, dp[y][s][e] + dp[z][e][t]);
		}
	}
	
	if (z == f) {
		for (int t = 0; t < L; t++) {
			update(x, t, e, dp[y][t][s] + dp[z][s][e]);
		}
	}
}

int main() {
	int g, n, m;
	ignore = scanf("%d %d %d", &g, &n, &m);
	
	for (int i = 0, it = 0, k; i < n; i++) {
		ignore = scanf("%d %d", a + i, &k);
		
		firstB[i] = it;
		for (int j = 0; j < k; j++) {
			ignore = scanf("%d", b + (it++));
		}
		
		lastB[i] = it;
	}
	
	simplifyMutations(n, g);
	
	L = AhoCorasick::create(m);
	
	for (int s = 0; s < L; s++) {
		for (int c = 0; c < 2; c++) {
			if (AhoCorasick::to[s][c] == -1) continue;
			
			update(c, s, AhoCorasick::to[s][c], 1);
		}
	}
	
	while (S.empty() == false) {
		int f, s, e;
		tie(ignore, f, s, e) = *S.begin();
		
		S.erase(S.begin());
		
		for (int i : mutations[f]) recalcMutationFast(i, f, s, e);
	}
	
	for (int i = 2; i < g; i++) {
		Int ans;
		for (int s = 0; s < L; s++)
			for (int e = 0; e < L; e++)
				ans = min(dp[i][s][e], ans);
		
		if (ans.x == Int::INF) printf("%s\n", "YES");
		else printf("%s %llu\n", "NO", ans.x);
	}
	
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...