【AtCoder】ABC 447 C - Insert and Erase A

実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 326 / NoviSteps: 2Q / 配点: 300 点
問題概要
英大文字からなる文字列 が与えられる。 あなたは以下の 種類の操作を好きな順序で 回以上行うことができる。
- の好きな位置(先頭および末尾を含む)に文字
Aを つ挿入する。 - に含まれる文字
Aを つ選んで削除する。なお、残った文字は元の順序を保ったまま連結される。
を に一致させることが可能かどうか判定し、可能な場合は必要な操作回数の合計の最小値を求めよ。
制約
考察
操作によって変更を加えられるのは文字列内のAの個数のみであるから、 と の両方から文字Aを全て取り除いた文字列をそれぞれ としたとき、 ならば、 にすることは不可能である。
その後、 と をA以外の文字で分割し、それぞれの区間に含まれるAの個数を数える配列 を作る。
サンプルケース3で言えば、以下のようになる。
ある区間でAを削除して別の区間にAを追加すると、合計2回の操作になる。
これは、それぞれの区間で独立して削除と追加を行うのと同じコストであるから、各区間ごとに独立して のAの数を の対応する区間のAの数に合わせるのが最適である。
したがって、求めるべき答えは となる。
実装例
1.#include <bits/stdc++.h>2.using namespace std;3. 4.#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)5. 6.// ======================================== //7. 8.int main()9.{10. string S, T;11. cin >> S >> T;12. 13. vector<int> s_a_cnts, t_a_cnts;14. string s_no_a, t_no_a;15. int cnt_s = 0, cnt_t = 0;16. for (char c : S)17. {18. if (c == 'A')19. {20. cnt_s++;21. }22. else23. {24. s_no_a += c;25. s_a_cnts.push_back(cnt_s);26. cnt_s = 0;27. }28. }29. s_a_cnts.push_back(cnt_s);30. 31. for (char c : T)32. {33. if (c == 'A')34. {35. cnt_t++;36. }37. else38. {39. t_no_a += c;40. t_a_cnts.push_back(cnt_t);41. cnt_t = 0;42. }43. }44. t_a_cnts.push_back(cnt_t);45. 46. if (s_no_a != t_no_a)47. {48. cout << -1 << endl;49. return 0;50. }51. 52. int ans = 0;53. rep(i, 0, s_a_cnts.size())54. {55. ans += abs(s_a_cnts[i] - t_a_cnts[i]);56. }57. 58. cout << ans << endl;59. 60. return 0;61.}実装時間: 10分
コメント
この問題、サンプルケースにA以外の文字が連続するケースがないので、 をランレングス圧縮によって構築するような解法がサンプルを通ってしまうのがちょっと怖いなと思った。





