[COCI2020-2021#3] Vlak
題意
Nina 和 Emilija 在玩遊戲。
Nina 先手,兩人輪流在紙上寫下一個字母。
每個玩家寫下字母后得到的單詞必須是該玩家喜歡的歌曲中某個單詞的字首。
不能操作的玩家輸,判斷最後誰會贏。
思路
對每個玩家喜歡的歌曲建立字典樹。
搜尋每個玩家的操作,每次在兩個字典樹上移動。
最多把字典樹的每個節點訪問一遍,時間複雜度 \(O(n)\)。
程式碼
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
struct Trie {
int son[N][27], cnt = 1;
void insert(string s) {
int p = 1;
for (auto c : s) {
int num = c - 'a', &q = son[p][num];
q = (!q ? ++ cnt : q), p = q;
}
}
} Nina, Emil;
int n, m;
bool dfs(int Np, int Ep, int state) {
if (!state) {
bool res = 0;
for (int i = 0; i < 26; i ++) {
if (!Nina.son[Np][i]) continue;
res |= !dfs(Nina.son[Np][i], Emil.son[Ep][i], !state);
}
return res;
} else {
bool res = 0;
for (int i = 0; i < 26; i ++) {
if (!Emil.son[Ep][i]) continue;
res |= !dfs(Nina.son[Np][i], Emil.son[Ep][i], !state);
}
return res;
}
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i ++) {
string s; cin >> s;
Nina.insert(s);
}
cin >> m;
for (int i = 1; i <= m; i ++) {
string s; cin >> s;
Emil.insert(s);
}
bool ans = dfs(1, 1, 0);
if (ans) cout << "Nina\n";
else cout << "Emilija\n";
}
int main() {
int T = 1;
// cin >> T;
while (T --)
solve();
return 0;
}