AUPC 2018 day3 F: Binary String with Slit

問題

01からなる文字列が与えられる。
文字列に対して次の操作を好きなだけ行える。
文字列の一番右の'1'を含む連続する二文字の部分文字列を

  • 11は10に
  • 10は11か01に
  • 01は10に

することができる。
文字列S, Tが与えられたとき、SをTに最低何回の操作で変えられるか。

制約

S, Tの長さは50以下で、それが10^5個以下与えられる。
S, Tは0,1からなり、ともに少なくとも一つの1を含む。

方針

一番右の1とその両隣しか操作できないので、
S, Tのうち異なる場所のうち一番左まで0にして100....0000のようにしないといけない。
その後は1を右に動かしていく。
前半は一回の操作で1文字消えて、後半は一回の操作で1文字確定するので明らかにこれが最適。
なので愚直に頭の中か紙の上でシミュレーションする。

ソースコード

int solve(){
	string s, t; cin >> s >> t;
	int n = s.size();
	int p = 0, s1 = n - 1, t1 = n - 1;
	for(; p < n && s[p] == t[p]; p++);
	if(p == n) return 0;
	for(; s1 >= 0 && s[s1] == '0'; s1--);
	for(; t1 >= 0 && t[t1] == '0'; t1--);
	
	if(s1 < p) return t1 - s1;
	if(t1 < p) return s1 - t1;
	if(s1 == p) return t1 - s1;
	int ans = s1 - p - 1;
	if(t1 == p) return ans + 1;

	ans += 2;
	ans += t1 - p - 1;
	return ans;
}
int main() {
	cin.tie(0); cin.sync_with_stdio(0);
	int q; cin >> q;
	while(q--){
		cout << solve() << endl;
	}
	return 0;
}