SRM 488 div1 med: TheBoringStoreDivOne
SRM 488, やたらと boring が出てくるけど競プロer が「頭悪い」って言うのと似た空気を感じる。
解法
以前に似たような問題を解いています。
mayokoex.hatenablog.com
B の 2 つの連続部分文字列 C, D では, C の後半と D の後半部分は一致しなければなりません。
例えば, C = "abcdd", D = "cdd" とかだと, "cdd" が一致しているので OK ですが, C = "abaa", D = "ab" とかだと, 最後の 2 文字が "aa" と "ab" で異なるので, どう頑張っても 問題文の A+C と B+D を一致させることは出来ません。
C = "abcdd", D = "cdd" のように後半が一致している場合は, "ab" という差を A, B で作って, A+C, B+D を作れば A+C == B+D となり happy です。
ということで, map
J について調べるときは, 各連続部分文字列 A, B に対して, A と B の後半の差(例えば A = "abcbb", B = "abc" だったら 差は "bb") を見て, もしその差に対応する C と D の差があればそれが店の名前の候補になります。
その中で一番長い文字列を探せば OK です。
微妙に計算量が怪しい(O(n^5 log n) くらい?) と思いましたが 100ms かかってなかったです。
class TheBoringStoreDivOne { public: string find(string J, string B) { map<string, string> mp; int jn = J.size(), bn = B.size(); for (int l1 = 0; l1 < bn; l1++) for (int r1 = l1+1; r1 <= bn; r1++) { for (int l2 = r1; l2 < bn; l2++) for (int r2 = l2+1; r2 <= bn; r2++) { int len = min(r2-l2, r1-l1); if (B.substr(r2-len, len) != B.substr(r1-len, len)) continue; string s; if (r2-l2 > r1-l1) s = B.substr(l2, r2-l2-len); else s = B.substr(l1, r1-l1-len); auto it = mp.find(s); if (it == mp.end()) mp.insert(make_pair(s, B.substr(r2-len, len))); else { int size = it->second.size(); if (size < len || ((size == len) && (it->second) > B.substr(r1-len, len)) ) { it->second = B.substr(r1-len, len); } } } } string ret; for (int l1 = 0; l1 < jn; l1++) for (int r1 = l1+1; r1 <= jn; r1++) { for (int l2 = r1; l2 < jn; l2++) for (int r2 = l2+1; r2 <= jn; r2++) { int len = min(r2-l2, r1-l1); if (J.substr(l1, len) != J.substr(l2, len)) continue; string s; if (r2-l2 > r1-l1) s = J.substr(l2+len, r2-l2-len); else s = J.substr(l1+len, r1-l1-len); if (mp.find(s) == mp.end()) continue; else s = J.substr(l1, len)+s+mp[s]; if (ret.size() < s.size() || (ret.size() == s.size() && ret > s)) ret = s; } } return ret; } };