Official

C - Insert and Erase A Editorial by yuto1115


各操作は \(S\) に文字 A を追加/削除するものであることから、\(S\)A が連続する部分と A 以外の文字が現れる部分に分解して考えたいです。そこで、文字列 \(S'\) および数列 \(A_S\) を以下のように定義します。

  • \(S'\): \(S\) に含まれる A 以外の文字を全て取り出し、元の順序で連結して得られる文字列。
  • \(A_S\): \(S\)A 以外の文字が現れる場所で分割したとき、各ブロックに含まれる A の個数を前から順番に並べた列。より形式的には、\(S'\) の長さを \(n\) としたとき、\(A_S\) は長さ \(n+1\) の数列であり、\(i\) 番目の要素 \(A_S(i)\) は以下の値に等しい:
    • \(i= 1\) のとき、\(S\) に含まれる最初の A 以外の文字より前に現れる A の数
    • \(2 \leq i \leq n\) のとき、\(S\) に含まれる \(i-1\) 番目の A 以外の文字と、 \(i\) 番目の A 以外の文字の間に現れる A の数
    • \(i= n+1\) のとき、\(S\) に含まれる最後の A 以外の文字より後に現れる A の数
    • なお、\(S'\) が空文字列のとき、\(A_S(1)=|S|\)

例えば、\(S=\) ABAAACAA のとき、\(S'=\) BC\(A_S=(1,3,2)\) です。

文字列 \(T\) に対しても同様に \(T'\) および \(A_T\) を定義します。

では、各操作によって \(S'\) および \(A_S\) がどのように変化するかを観察してみましょう。すると、以下の事実が成り立つことが分かります。

  • 操作によって \(S'\) は変化しない。
  • \(1\) 種類目の操作では、ある \(i\) に対して \(A_S(i)\) の値が \(1\) 増加する。
  • \(2\) 種類目の操作では、ある \(i\) に対して \(A_S(i)\) の値が \(1\) 減少する。

逆に、\(1\) 回の操作では、(\(S'\) を保ったまま)好きな \(i\) に対して \(A_S(i)\) の値を \(1\) 増加または減少させることができます。

よって、本問題の答えは以下のように表せます:

  • \(S'\neq T'\) のとき、\(S\)\(T\) に一致させることはできない
  • \(S'= T'\) のとき、すべての \(i\ (1\leq i\leq |S'|+1)\) に対する \(|A_S(i) - A_T(i)|\) の総和

実装例 (C++) :

#include <bits/stdc++.h>

using namespace std;

pair<string, vector<int>> decompose(const string &s) {
    string t;
    vector<int> v;
    int cnt = 0;
    for (char c: s) {
        if (c == 'A') {
            ++cnt;
        } else {
            t += c;
            v.push_back(cnt);
            cnt = 0;
        }
    }
    v.push_back(cnt);
    return {t, v};
}

int main() {
    string s, t;
    cin >> s >> t;
    auto [ss, sv] = decompose(s);
    auto [ts, tv] = decompose(t);
    if (ss != ts) {
        cout << -1 << endl;
        return 0;
    }
    int ans = 0;
    for (int i = 0; i < (int) sv.size(); i++) {
        ans += abs(sv[i] - tv[i]);
    }
    cout << ans << endl;
}

posted:
last update: