#include <bits/stdc++.h>
using namespace std;
const int mx = 1e9;
struct Data {
  int p1, p2, p3, p4;
  Data(int a = mx, int b = mx, int c = mx, int d = mx) {
    p1 = a, p2 = b, p3 = c, p4 = d;
  }
};
inline Data UN(Data a, Data b) {
  Data c;
  c.p1 = min(a.p1 + b.p1, a.p2 + b.p3), c.p2 = min(a.p1 + b.p2, a.p2 + b.p4);
  c.p3 = min(a.p3 + b.p1, a.p4 + b.p3), c.p4 = min(a.p3 + b.p2, a.p4 + b.p4);
  c.p1 = min(c.p1, mx), c.p2 = min(c.p2, mx), c.p3 = min(c.p3, mx),
  c.p4 = min(c.p4, mx);
  return c;
}
struct node {
  int l, r;
  Data s;
} T[200010 << 2];
char G[3][200010];
void build(int rt, int l, int r) {
  T[rt].l = l, T[rt].r = r;
  int mid = (l + r) >> 1;
  if (l == r) {
    if (G[1][l] == '.') T[rt].s.p1 = 1;
    if (G[2][l] == '.') T[rt].s.p4 = 1;
    if (G[1][l] == '.' && G[2][l] == '.') T[rt].s.p2 = T[rt].s.p3 = 2;
    return;
  }
  build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
  T[rt].s = UN(T[rt << 1].s, T[rt << 1 | 1].s);
}
Data query(int rt, int start, int end) {
  int l = T[rt].l, r = T[rt].r, mid = (l + r) >> 1;
  if (start <= l && r <= end) return T[rt].s;
  if (end <= mid) return query(rt << 1, start, end);
  if (start > mid) return query(rt << 1 | 1, start, end);
  return UN(query(rt << 1, start, end), query(rt << 1 | 1, start, end));
}
int main() {
  int n, q;
  scanf("%d%d", &n, &q);
  scanf("%s%s", G[1] + 1, G[2] + 1);
  build(1, 1, n);
  while (q--) {
    int a, b;
    scanf("%d%d", &a, &b);
    int l = a > n ? a - n : a, r = b > n ? b - n : b, res;
    if (l > r) swap(l, r), swap(a, b);
    Data tmp = query(1, l, r);
    if (a <= n && b <= n) res = tmp.p1;
    if (a <= n && b > n) res = tmp.p2;
    if (a > n && b <= n) res = tmp.p3;
    if (a > n && b > n) res = tmp.p4;
    if (res < 1e8)
      printf("%d\n", res - 1);
    else
      printf("-1\n");
  }
  return 0;
}
