Official
C - Insert and Erase A Editorial
by
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|\)
- \(i= 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: