#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
const int inf = 1e9;
int n, m;
int mp[3][N];
char ch[N];
struct node {
  int d1, d2, d3, d4;
};
struct tree {
  int l, r;
  node d;
} t[N * 5];
node merge(node a, node b) {
  node tmp;
  tmp.d1 = min(inf, min(a.d1 + b.d1, a.d2 + b.d3) + 1);
  tmp.d2 = min(inf, min(a.d1 + b.d2, a.d2 + b.d4) + 1);
  tmp.d3 = min(inf, min(a.d3 + b.d1, a.d4 + b.d3) + 1);
  tmp.d4 = min(inf, min(a.d3 + b.d2, a.d4 + b.d4) + 1);
  return tmp;
}
inline void build(int x, int l, int r) {
  t[x].l = l, t[x].r = r;
  if (l == r) {
    t[x].d.d1 = t[x].d.d2 = t[x].d.d3 = t[x].d.d4 = inf;
    if (mp[1][l]) t[x].d.d1 = 0;
    if (mp[2][l]) t[x].d.d4 = 0;
    if (mp[1][l] && mp[2][l]) t[x].d.d2 = t[x].d.d3 = 1;
    return;
  }
  int mid = (l + r) >> 1;
  build(x << 1, l, mid);
  build(x << 1 | 1, mid + 1, r);
  t[x].d = merge(t[x << 1].d, t[x << 1 | 1].d);
}
inline node query(int x, int l, int r) {
  if (l == t[x].l && r == t[x].r) return t[x].d;
  int mid = (t[x].l + t[x].r) >> 1;
  if (r <= mid)
    return query(x << 1, l, r);
  else if (l > mid)
    return query(x << 1 | 1, l, r);
  else
    return merge(query(x << 1, l, mid), query(x << 1 | 1, mid + 1, r));
}
inline int ask(int x, int y) {
  int a = (x - 1) % n + 1, b = (y - 1) % n + 1;
  if (a > b) {
    swap(x, y);
    swap(a, b);
  }
  node tmp = query(1, a, b);
  if (x <= n && y <= n) return tmp.d1;
  if (x <= n && y > n) return tmp.d2;
  if (x > n && y <= n) return tmp.d3;
  if (x > n && y > n) return tmp.d4;
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= 2; i++) {
    scanf("%s", ch);
    for (int j = 1; j <= n; j++)
      if (ch[j - 1] == '.') mp[i][j] = 1;
  }
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    int ans = ask(x, y);
    if (ans < inf)
      printf("%d\n", ans);
    else
      printf("-1\n");
  }
  return 0;
}
