https://beta.atcoder.jp/contests/code-festival-2018-final-open/tasks/code_festival_2018_final_d
解説
https://beta.atcoder.jp/contests/code-festival-2018-final-open/submissions/3622829
O(90000*52*52)を目指す。
まず、encode関数を用意して、全ての文字を大小関係を保ちながら0~51にしておこう。
i,jを全探索する。
このi,jについてkを数えていく。
n番目の文字列について、i,jの位置は先頭から順番に決める。
すると、j以降の要素は全てkになることができる。
この文字についてvisを更新しておき、最後にcntで数え上げる。
注意することがあるが、visを文字列毎に初期化して使うことになるが、注意しないとO(30000*52^3)になってしまいTLEする。
O(90000*52*52)を守ろう。
あとは、(-満たす文字列の組み合わせ,i,j,k)のtupleを作り、最小となるものが答え。
int N; string A[30101]; int M[301010]; using T = tuple<int, int, int, int>; //--------------------------------------------------------------------------------------------------- int encode(char c) { if ('A' <= c and c <= 'Z') return c - 'A'; return c - 'a' + 26; } char decode(int i) { if (i < 26) return char('A' + i); return char('a' + i - 26); } //--------------------------------------------------------------------------------------------------- int cnt[52], vis[52]; void _main() { cin >> N; rep(i, 0, N) { cin >> A[i]; M[i] = A[i].length(); fore(c, A[i]) c = encode(c); } T ans = make_tuple(inf, inf, inf, inf); rep(i, 0, 52) rep(j, 0, 52) { rep(n, 0, N) { int idx = 0; while (idx < M[n] and A[n][idx] != i) idx++; idx++; while (idx < M[n] and A[n][idx] != j) idx++; idx++; rep(m, idx, M[n]) vis[A[n][m]] = 1; rep(m, idx, M[n]) if (vis[A[n][m]]) { cnt[A[n][m]]++; vis[A[n][m]] = 0; } } rep(k, 0, 52) if(cnt[k]) { chmin(ans, make_tuple(-cnt[k], i, j, k)); cnt[k] = 0; } } int ma, i, j, k; tie(ma, i, j, k) = ans; printf("%c%c%c\n", decode(i), decode(j), decode(k)); }