#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
const int inf = 1000000000;
int n, m, ans, a[3][N];
char s[N];
struct SegmentTree {
  int d[4];
  inline int& operator[](const int x) { return d[x]; }
} t[N << 2];
inline SegmentTree merge(SegmentTree x, SegmentTree y) {
  SegmentTree p;
  p[0] = min(inf, min(x[0] + y[0], x[1] + y[2]) + 1);
  p[1] = min(inf, min(x[0] + y[1], x[1] + y[3]) + 1);
  p[2] = min(inf, min(x[3] + y[2], x[2] + y[0]) + 1);
  p[3] = min(inf, min(x[3] + y[3], x[2] + y[1]) + 1);
  return p;
}
inline void build(int p, int l, int r) {
  if (l == r) {
    t[p][0] = t[p][1] = t[p][2] = t[p][3] = inf;
    if (a[1][l]) t[p][0] = 0;
    if (a[2][l]) t[p][3] = 0;
    if (a[1][l] && a[2][l]) t[p][1] = t[p][2] = 1;
    return;
  }
  int mid = l + r >> 1;
  build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
  t[p] = merge(t[p << 1], t[p << 1 | 1]);
}
inline SegmentTree query(int p, int l, int r, int L, int R) {
  if (L == l && r == R) return t[p];
  int mid = l + r >> 1;
  if (mid >= R)
    return query(p << 1, l, mid, L, R);
  else if (mid < L)
    return query(p << 1 | 1, mid + 1, r, L, R);
  else
    return merge(query(p << 1, l, mid, L, mid),
                 query(p << 1 | 1, mid + 1, r, mid + 1, R));
}
inline int ask(int x, int y) {
  int p = (x - 1) % n + 1, q = (y - 1) % n + 1;
  if (p > q) swap(x, y), swap(p, q);
  SegmentTree res = query(1, 1, n, p, q);
  if (x <= n && y <= n) return res[0];
  if (x <= n && y > n) return res[1];
  if (x > n && y <= n) return res[2];
  if (x > n && y > n) return res[3];
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= 2; i++) {
    scanf("%s", s + 1);
    for (int j = 1; j <= n; j++)
      if (s[j] == '.') a[i][j] = 1;
  }
  build(1, 1, n);
  int x, y;
  for (int i = 1; i <= m; i++) {
    scanf("%d%d", &x, &y);
    int res = ask(x, y);
    printf("%d\n", res < inf ? res : -1);
  }
  return 0;
}
