// ===== 2019/03/30 23:11:17 =====

// includes.hpp

#include <algorithm>
#include <array>
#include <cassert>
#include <climits>
#include <complex>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <tuple>
#include <vector>

// cin.cpp

template <typename T, int M, int N> struct tuple_getter {
  static void get(std::istream &is, T &x) {
    is >> std::get<M>(x);
    tuple_getter<T, M + 1, N>::get(is, x);
  }
};

template <typename T, int N> struct tuple_getter<T, N, N> {
  static void get(std::istream &is, T &x) { is >> std::get<N>(x); }
};

template <typename... Args>
std::istream &operator>>(std::istream &is, std::tuple<Args...> &t) {
  tuple_getter<std::tuple<Args...>, 0, sizeof...(Args) - 1>::get(is, t);
  return is;
}

template <typename T, typename U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
  for (T &x : v) is >> x;
  return is;
}

// const_value.hpp

namespace sub {
template <typename T>
constexpr typename std::enable_if<std::is_integral<T>::value, T>::type
inf_sub() {
  return std::numeric_limits<T>::max() / 2 - 1000;
}

template <typename T>
constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
inf_sub() {
  return std::min(std::numeric_limits<T>::max() / 2 - 1000, T(1e50));
}
}  // namespace sub

template <typename T> constexpr T inf() {
  static_assert(std::is_arithmetic<T>::value, "T must be arithmetic value");
  return sub::inf_sub<T>();
}

template <typename T> constexpr T zero() {
  static_assert(std::is_arithmetic<T>::value, "T must be arithmetic value");
  return T(0);
}

const long double pi = acos(-1.0);

// cout.cpp

template <typename T, int M, int N> struct tuple_printer {
  static void print(std::ostream &os, const T &x) {
    os << std::get<M>(x) << " ";
    tuple_printer<T, M + 1, N>::print(os, x);
  }
};

template <typename T, int N> struct tuple_printer<T, N, N> {
  static void print(std::ostream &os, const T &x) { os << std::get<N>(x); }
};

template <typename... Args>
std::ostream &operator<<(std::ostream &os, const std::tuple<Args...> &t) {
  tuple_printer<std::tuple<Args...>, 0, sizeof...(Args) - 1>::print(os, t);
  return os;
}

template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
  for (auto it = v.begin(); it != v.end(); ++it) {
    if (it != v.begin()) os << " ";
    os << *it;
  }
  return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::set<T> &v) {
  for (auto it = v.begin(); it != v.end(); ++it) {
    if (it != v.begin()) os << " ";
    os << *it;
  }
  return os;
}

// macros.hpp

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define ALL(x) (x).begin(), (x).end()

// misc.hpp

template <typename T> T &chmin(T &a, const T &b) { return a = std::min(a, b); }

template <typename T> T &chmax(T &a, const T &b) { return a = std::max(a, b); }

// range.hpp

class range {
  class index_type {
    int x;

  public:
    index_type(int x_) : x(x_) {}
    int operator*() const { return x; }
    bool operator!=(index_type &r) { return x < r.x; }
    void operator++() { ++x; }
  };
  index_type i, n;

public:
  range(int n_) : i(0), n(n_) {}
  range(int i_, int n_) : i(i_), n(n_) {}
  index_type &begin() { return i; }
  index_type &end() { return n; }
};

// typedef.hpp

using ll = long long;
using ld = long double;

// template.cpp

using namespace std;

// main.cpp

template <typename T> vector<T> table(int n, T v) { return vector<T>(n, v); }

template <class... Args> auto table(int n, Args... args) {
  auto val = table(args...);
  return vector<decltype(val)>(n, move(val));
}

char S[100100];
char T[100100];

int subtask(int sy, int sx, int ty, int tx) {
  if (sy == ty) {
    if (sx == tx) return 0;
    if (sx < tx && S[sy] == 'E') return 0;
    if (sx > tx && S[sy] == 'W') return 0;
  }
  if ((sy < ty && T[sx] == 'S') || (sy > ty && T[sx] == 'N')) {
    if (sx == tx) return 0;
    if (sx < tx && S[ty] == 'E') return 0;
    if (sx > tx && S[ty] == 'W') return 0;
  }
  if ((sy < ty && T[tx] == 'S') || (sy > ty && T[tx] == 'N')) {
    if (sx == tx) return 0;
    if (sx < tx && S[sy] == 'E') return 0;
    if (sx > tx && S[sy] == 'W') return 0;
  }
  return 1e9;
}

set<int> n, s, e, w;

vector<tuple<int,int,int>> next_point(int sy, int sx) {
  vector<tuple<int,int,int>> res;
  REP(sdir,2) {
    int nsy = sy, nsx = sx, nsum = 0;
    if (sdir == 0) {
      if (S[sy] == 'E' && T[sx] == 'N') {
        auto it = s.lower_bound(sx);
        if (it == s.end()) continue;
        nsx = *it;
      }
      if (S[sy] == 'W' && T[sx] == 'N') {
        auto it = s.lower_bound(sx);
        if (it == s.begin()) continue;
        nsx = *prev(it);
      }
      if (S[sy] == 'E' && T[sx] == 'S') {
        auto it = n.lower_bound(sx);
        if (it == n.end()) continue;
        nsx = *it;
      }
      if (S[sy] == 'W' && T[sx] == 'S') {
        auto it = n.lower_bound(sx);
        if (it == n.begin()) continue;
        nsx = *prev(it);
      }
      nsum += abs(nsx - sx);
    }
    if (sdir == 1) {
      if (S[sy] == 'E' && T[sx] == 'N') {
        auto it = w.lower_bound(sy);
        if (it == w.begin()) continue;
        nsy = *prev(it);
      }
      if (S[sy] == 'E' && T[sx] == 'S') {
        auto it = w.lower_bound(sy);
        if (it == w.end()) continue;
        nsy = *it;
      }
      if (S[sy] == 'W' && T[sx] == 'N') {
        auto it = e.lower_bound(sy);
        if (it == e.begin()) continue;
        nsy = *prev(it);
      }
      if (S[sy] == 'W' && T[sx] == 'S') {
        auto it = e.lower_bound(sy);
        if (it == e.end()) continue;
        nsy = *it;
      }
      nsum += abs(nsy - sy);
    }
    res.emplace_back(nsy, nsx, nsum);
  }
  return res;
}

vector<tuple<int,int,int>> prev_point(int sy, int sx) {
  vector<tuple<int,int,int>> res;
  REP(sdir,2) {
    int nsy = sy, nsx = sx, nsum = 0;
    if (sdir == 0) {
      if (S[sy] == 'W' && T[sx] == 'N') {
        auto it = s.lower_bound(sx + 1);
        if (it == s.end()) continue;
        nsx = *it;
      }
      if (S[sy] == 'E' && T[sx] == 'N') {
        auto it = s.lower_bound(sx);
        if (it == s.begin()) continue;
        nsx = *prev(it);
      }
      if (S[sy] == 'W' && T[sx] == 'S') {
        auto it = n.lower_bound(sx + 1);
        if (it == n.end()) continue;
        nsx = *it;
      }
      if (S[sy] == 'E' && T[sx] == 'S') {
        auto it = n.lower_bound(sx);
        if (it == n.begin()) continue;
        nsx = *prev(it);
      }
      nsum += abs(nsx - sx);
    }
    if (sdir == 1) {
      if (S[sy] == 'E' && T[sx] == 'S') {
        auto it = w.lower_bound(sy);
        if (it == w.begin()) continue;
        nsy = *prev(it);
      }
      if (S[sy] == 'E' && T[sx] == 'N') {
        auto it = w.lower_bound(sy + 1);
        if (it == w.end()) continue;
        nsy = *it;
      }
      if (S[sy] == 'W' && T[sx] == 'S') {
        auto it = e.lower_bound(sy);
        if (it == e.begin()) continue;
        nsy = *prev(it);
      }
      if (S[sy] == 'W' && T[sx] == 'N') {
        auto it = e.lower_bound(sy + 1);
        if (it == e.end()) continue;
        nsy = *it;
      }
      nsum += abs(nsy - sy);
    }
    res.emplace_back(nsy, nsx, nsum);
  }
  return res;
}

void solve(long long N, long long M, long long Q, std::string S, std::string T,
           std::vector<long long> a, std::vector<long long> b,
           std::vector<long long> c, std::vector<long long> d) {
  // FILL IN HERE.
  REP(i,N) {
    if (S[i] == 'E') e.insert(i);
    if (S[i] == 'W') w.insert(i);
  }
  REP(i,M) {
    if (T[i] == 'N') n.insert(i);
    if (T[i] == 'S') s.insert(i);
  }
  REP(i,Q) {
    int sy = a[i];
    int sx = b[i];
    int ty = c[i];
    int tx = d[i];
    --sy; --sx; --ty; --tx;
    int sum = abs(sy - ty) + abs(sx - tx);
    if (subtask(sy, sx, ty, tx) == 0) {
      cout << sum << endl;
      continue;
    }
    int res = 1e9;
    vector<tuple<int,int,int>> starts;
    vector<tuple<int,int,int>> goals;

    starts.emplace_back(sy, sx, 0);
    for (auto t: next_point(sy, sx)) {
      int y1, x1, sum1;
      tie(y1, x1, sum1) = t;
      // cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
      starts.emplace_back(t);
      for (auto t: next_point(y1, x1)) {
        get<2>(t) += sum1;
        // cout << "  " << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
        starts.emplace_back(t);
      }
    }

    goals.emplace_back(ty, tx, 0);
    for (auto t: prev_point(ty, tx)) {
      int y1, x1, sum1;
      tie(y1, x1, sum1) = t;
      // cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
      goals.emplace_back(t);
      for (auto t: prev_point(y1, x1)) {
        get<2>(t) += sum1;
        // cout << "  " << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
        goals.emplace_back(t);
      }
    }

    for (auto s: starts) {
      for (auto t: goals) {
        int sy, sx, sums;
        int ty, tx, sumt;
        tie(sy, sx, sums) = s;
        tie(ty, tx, sumt) = t;
        chmin(res, sums + sumt + subtask(sy, sx, ty, tx) + abs(sy - ty) + abs(sx - tx));
      }
    }

    if (res >= 1e9) cout << -1 << endl;
    else cout << res << endl;
  }
}

int main() {
  long long N;
  scanf("%lld", &N);
  long long M;
  scanf("%lld", &M);
  long long Q;
  scanf("%lld", &Q);
  scanf("%s", S);
  scanf("%s", T);
  std::vector<long long> a(Q);
  std::vector<long long> b(Q);
  std::vector<long long> c(Q);
  std::vector<long long> d(Q);
  for (int i = 0; i < Q; i++) {
    scanf("%lld", &a[i]);
    scanf("%lld", &b[i]);
    scanf("%lld", &c[i]);
    scanf("%lld", &d[i]);
  }
  solve(N, M, Q, S, T, std::move(a), std::move(b), std::move(c), std::move(d));
  return 0;
}

// ===== 2019/03/30 23:11:17 =====


Measured memory_bytes: 17536