Problem:
Score : 1000 points

Problem Statement

You have two strings A = A_1 A_2 ... A_n and B = B_1 B_2 ... B_n of the same length consisting of 0 and 1.

You can transform A using the following operations in any order and as many times as you want:

Shift A by one character to the left (i.e., if A = A_1 A_2 ... A_n, replace A with A_2 A_3 ... A_n A_1).

Shift A by one character to the right (i.e., if A = A_1 A_2 ... A_n, replace A with A_n A_1 A_2 ... A_{n-1}).

Choose any i such that B_i = 1. Flip A_i (i.e., set A_i = 1 - A_i).

You goal is to make strings A and B equal.

Print the smallest number of operations required to achieve this, or -1 if the goal is unreachable.

Constraints

1 \leq |A| = |B| \leq 2,000

A and B consist of 0 and 1.

Input

Input is given from Standard Input in the following format:

A
B

Output

Print the smallest number of operations required to make strings A and B equal, or -1 if the goal is unreachable.

Sample Input 1

1010
1100

Sample Output 1

3

Here is one fastest way to achieve the goal:

Flip A_1: A = 0010

Shift A to the left: A = 0100

Flip A_1 again: A = 1100

Sample Input 2

1
0

Sample Output 2

-1

There is no way to flip the only bit in A.

Sample Input 3

11010
10001

Sample Output 3

4

Here is one fastest way to achieve the goal:

Shift A to the right: A = 01101

Flip A_5: A = 01100

Shift A to the left: A = 11000

Shift A to the left again: A = 10001

Sample Input 4

0100100
1111111

Sample Output 4

5

Flip A_1, A_3, A_4, A_6 and A_7 in any order.

Solution in C++14 (GCC 5.4.1) (judge verdict: Runtime Error)

#include <bits/stdc++.h>
using namespace std;
using P = pair<int, int>;

const function<int(int, int)> maxQ = [](int l, int r) { return max(l, r); };

template <typename T>
class SegmentTree {
	using func_t = function<T(T, T)>;
	const int n;
	const T id;
	func_t merge;
	vector<T> data;
	int size(int n) {
		int res;
		for (res = 1; res < n; res <<= 1);
		return res;
	}
public:
	SegmentTree(int n_, T id_, func_t merge_) :
		n(size(n_)), id(id_), merge(merge_), data(n * 2, id) {}
	void Init(const vector<T>& data_) {
		for (int i = 0; i < (int)data_.size(); i++)
			data[i + n] = data_[i];
		for (int i = n - 1; i >= 0; i--)
			data[i] = merge(data[i * 2], data[i * 2 + 1]);
	}
	void Update(int p, T val) {
		p += n;
		data[p] = val;
		while (p >>= 1) data[p] = merge(data[p * 2], data[p * 2 + 1]);
	}
	void Add(int p, T val) {
		p += n;
		data[p] += val;
		while (p >>= 1) data[p] = merge(data[p * 2], data[p * 2 + 1]);
	}
	T Find(int i) {
		return data[i + n];
	}
	T Find(int l, int r) {
		l = max(l, 0);
		r = min(r, n - 1);
		l += n; r += n + 1;
		T res1 = id, res2 = id;
		while (l < r) {
			if (l & 1) res1 = merge(res1, data[l++]);
			if (r & 1) res2 = merge(data[--r], res2);
			l >>= 1; r >>= 1;
		}
		return merge(res1, res2);
	}
};

int main()
{
	string A, B;
	cin >> A >> B;
	int N = A.size();
	bool pre = false;
	for (int i = 0; i < N; i++) {
		if (A[i] == '1') {
			pre = true;
			break;
		}
	}
	for (int i = 0; i < N; i++) {
		if (B[i] == '1') {
			pre = false;
			break;
		}
	}
	if (pre) {
		cout << -1 << endl;
		return 0;
	}
	vector<int> ko;
	for (int i = 0; i < N; i++) {
		if (B[i] == '1') {
			ko.push_back(i);
		}
	}
	int res = 1e8;
	for (int i = 0; i < N; i++) {
		int cnt = 0;
		vector<P> lr;
		for (int j = 0; j < N; j++) {
			if (A[(j + i) % N] != B[j]) {
				cnt++;
				int ri = lower_bound(ko.begin(), ko.end(), (j + i) % N) - ko.begin();
				if (ri == (int)ko.size()) ri = abs(N - 1 - (j + i) % N) + ko.front() + 1;
				else ri = abs(ko[ri] -  (j + i) % N);
				int le = (upper_bound(ko.begin(), ko.end(), (j + i) % N) - ko.begin()) - 1;
				if (le < 0) le = abs(N - 1 - ko.back()) + (j + i) % N + 1;
				else le = abs(ko[le] - (j + i) % N);
				lr.emplace_back(-le, ri);
			}
		}
		sort(lr.begin(), lr.end());
		SegmentTree<int> st(cnt, 0, maxQ);
		for (int j = 0; j < cnt; j++) {
			st.Update(j, lr[j].second);
		}
		int val = min(min(max(-lr[0].first - i, 0) * 2, st.Find(0, cnt - 1) * 2), N) + i;
		val = min(val, N - 1 - i + max(st.Find(0, cnt - 1) - (N - 1 - i), 0));
		for (int j = 0; j < cnt; j++) {
			int id = upper_bound(lr.begin(), lr.end(), P(lr[j].first, N * 10)) - lr.begin();
			if (id < 0 || id >= cnt) break;
			val = min(val, max(-lr[id].first - i, 0) * 2 + st.Find(0, id - 1) * 2 + i);
			val = min(val, (-lr[id].first) * 2 + max(st.Find(0, id - 1) - (N - 1 - i), 0) * 2 + (N - 1 - i));
			j = id - 1;
		}
		res = min(res, val + cnt);
	}
	cout << res << endl;
	return 0;
}