//リメイク版出題ありがとうございます!(@startcpp) //考察: // //先頭i文字目から"good"、先頭j文字目から"problem"を作ることを考える。(j >= i + 4) //このとき、goodを作るためのコストをg[i], problemを作るためのコストをp[j]とする。 //すると、g[i] + p[j]がこの時の良問のコストであり、g[i] + p[j]の最小値が本問の答え。 //…と思いたいが、"good"の前に"problem"がある場合は、それを壊す必要があるのでそのコストも考慮する必要がある。 //壊すコストは、i-1文字目までにある"problem"の個数となる。 #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; int gethamming(char *s, char *t, int len); int t; char s[1000002]; int g[1000000]; int p[1000000]; multiset minP; signed main() { cin >> t; while (t--) { cin >> s; int slen = strlen(s); for (int i = 0; i < slen - 10; i++) { g[i] = gethamming("good", s + i, 4); } for (int i = 4; i < slen - 6; i++) { p[i] = gethamming("problem", s + i, 7); minP.insert(p[i]); } int breakcost = 0; int ans = 114514; for (int i = 0; i < slen - 10; i++) { if (i > 0 && gethamming("problem", s + i - 1, 7) == 0) { breakcost++; } //p[i+4]~p[slen-6]の中の最小値を求めてans更新なり ans = min(ans, g[i] + *minP.begin() + breakcost); //p[i+4]を集合から削除っと multiset::iterator it = minP.find(p[i+4]); if (it != minP.end() ) minP.erase(it); } cout << ans << endl; } return 0; } int gethamming(char *s, char *t, int len) { int score = 0; for (int i = 0; i < len; i++) score += (s[i] != t[i]); return score; }