Problem:
Score : 1200 points

Problem Statement

In Takaha-shi, the capital of Republic of AtCoder, there are N roads extending east and west, and M roads extending north and south. There are no other roads.
The i-th east-west road from the north and the j-th north-south road from the west cross at the intersection (i, j).
Two east-west roads do not cross, nor do two north-south roads.
The distance between two adjacent roads in the same direction is 1.

Each road is one-way; one can only walk in one direction. The permitted direction for each road is described by a string S of length N and a string T of length M, as follows:

If the i-th character in S is W, one can only walk westward along the i-th east-west road from the north;

If the i-th character in S is E, one can only walk eastward along the i-th east-west road from the north;

If the i-th character in T is N, one can only walk northward along the i-th north-south road from the west;

If the i-th character in T is S, one can only walk southward along the i-th south-west road from the west.

Process the following Q queries:

In the i-th query, a_i, b_i, c_i and d_i are given. What is the minimum distance to travel to reach the intersection (c_i, d_i) from the intersection (a_i, b_i) by walking along the roads?

Constraints

2 \leq N \leq 100000

2 \leq M \leq 100000

2 \leq Q \leq 200000

|S| = N

S consists of W and E.

|T| = M

T consists of N and S.

1 \leq a_i \leq N

1 \leq b_i \leq M

1 \leq c_i \leq N

1 \leq d_i \leq M

(a_i, b_i) \neq (c_i, d_i)

Input

Input is given from Standard Input in the following format:

N M Q
S
T
a_1 b_1 c_1 d_1
a_2 b_2 c_2 d_2
:
a_Q b_Q c_Q d_Q

Output

In the i-th line, print the response to the i-th query. If the intersection (c_i, d_i) cannot be reached from the intersection (a_i, b_i) by walking along the roads, print -1 instead.

Sample Input 1

4 5 4
EEWW
NSNNS
4 1 1 4
1 3 1 2
4 2 3 2
3 3 3 5

Sample Output 1

6
11
5
4

The permitted direction for each road is shown in the following figure (north upward):

For each of the four queries, a route that achieves the minimum travel distance is as follows:

Sample Input 2

3 3 2
EEE
SSS
1 1 3 3
3 3 1 1

Sample Output 2

4
-1

The travel may be impossible.

Sample Input 3

9 7 10
EEEEEWEWW
NSSSNSN
4 6 9 2
3 7 6 7
7 5 3 5
1 1 8 1
4 3 5 4
7 4 6 4
2 5 8 6
6 6 2 7
2 4 7 5
7 2 9 7

Sample Output 3

9
-1
4
9
2
3
7
7
6
-1

Solution in Rust (1.15.1) (judge verdict: Accepted)

#![allow(non_snake_case)]
//////////////////////////////// LIBRARY START ////////////////////////////////
#[macro_use]
pub mod contest {
    #[macro_use]
    pub mod io {
        /// Scanner
        ///
        /// # Example
        /// ```
        /// use contest::io::Scanner;
        /// let mut sc = Scanner::new("1 2 \n\n \r\t \n 3.5".as_bytes());
        /// assert_eq!("1".to_string(), sc.next::<String>());
        /// assert_eq!(2, sc.next());
        /// assert_eq!(3.5, sc.next());
        ///
        /// // To create a scanner from stdin:
        /// Scanner::new(std::io::stdin());
        /// ```
        use std;
        use std::io;
        use std::io::BufRead;

        pub struct Scanner<R: io::Read> {
            br: io::BufReader<R>,
            // Read tokens are stored in reversed order per line.
            buf: Vec<String>,
        }

        pub fn new<R: io::Read>(r: R) -> Scanner<R> {
            Scanner::new(r)
        }

        impl<R: io::Read> Scanner<R> {
            #[inline]
            pub fn new(r: R) -> Scanner<R> {
                Scanner {
                    br: io::BufReader::new(r),
                    buf: vec![],
                }
            }
            #[inline]
            pub fn next<T>(&mut self) -> T
            where
                T: std::str::FromStr,
                T::Err: std::fmt::Debug,
            {
                self.next_string()
                    .map(|s| s.parse::<T>().expect("Parse failed: "))
                    .expect("Unexpected EOF")
            }
            #[inline]
            pub fn next2<T1, T2>(&mut self) -> (T1, T2)
            where
                T1: std::str::FromStr,
                T2: std::str::FromStr,
                T1::Err: std::fmt::Debug,
                T2::Err: std::fmt::Debug,
            {
                (self.next(), self.next())
            }
            fn next_string(&mut self) -> Option<String> {
                self.buf.pop().or_else(|| match self.update() {
                    true => self.next_string(),
                    false => None,
                })
            }
            #[inline]
            fn update(&mut self) -> bool {
                let mut s = String::new();
                let res = self.br.read_line(&mut s);
                match res.expect("I/O error.") {
                    0 => false,
                    _ => {
                        self.buf = s.split_whitespace().map(|x| x.to_string()).rev().collect();
                        true
                    }
                }
            }
        }

        #[test]
        fn test_next() {
            let mut sc = new("hoge".as_bytes());
            let s: String = sc.next();
            assert_eq!("hoge", s);
        }
    }
    #[macro_use]
    pub mod prelude {
        use std::fmt;
        use std::iter::FromIterator;
        use std::ops::*;

        /// `Vec` indexable with `i32`, `i64` or `usize`.
        #[derive(Clone, Debug, PartialEq, PartialOrd)]
        pub struct MyVec<T>(pub Vec<T>);

        /// Creates `MyVec`
        #[macro_export]
        macro_rules! v {
    ( $( $x:expr ),* ) => {
        MyVec(vec![ $( $x, )* ])
    };
    ( $x:expr ; $n:expr ) => {
        {
            MyVec(vec![$x; $n as usize])
        }
    };
}

        impl<T: fmt::Display> fmt::Display for MyVec<T> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                let n = self.len();
                for i in 0..n {
                    let r = if i < n - 1 {
                        writeln!(f, "{}", self.0[i])
                    } else {
                        write!(f, "{}", self.0[i])
                    };
                    if r.is_err() {
                        return r;
                    }
                }
                Ok(())
            }
        }

        impl<T> Deref for MyVec<T> {
            type Target = Vec<T>;

            #[inline]
            fn deref(&self) -> &Vec<T> {
                &self.0
            }
        }

        impl<T> DerefMut for MyVec<T> {
            #[inline]
            fn deref_mut(&mut self) -> &mut Vec<T> {
                &mut self.0
            }
        }

        impl<T> FromIterator<T> for MyVec<T> {
            #[inline]
            fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
                MyVec(Vec::from_iter(iter))
            }
        }

        impl<T, I: ToUsize> Index<I> for MyVec<T> {
            type Output = T;

            #[inline]
            fn index(&self, i: I) -> &T {
                &self.0[i.to_usize()]
            }
        }

        impl<T, I: ToUsize> IndexMut<I> for MyVec<T> {
            #[inline]
            fn index_mut(&mut self, i: I) -> &mut T {
                &mut self.0[i.to_usize()]
            }
        }

        pub trait ToUsize: Sized {
            fn to_usize(self) -> usize;
        }

        impl ToUsize for i32 {
            #[inline]
            fn to_usize(self) -> usize {
                self as usize
            }
        }

        impl ToUsize for i64 {
            #[inline]
            fn to_usize(self) -> usize {
                self as usize
            }
        }

        impl ToUsize for usize {
            #[inline]
            fn to_usize(self) -> usize {
                self
            }
        }

        #[test]
        fn test_myvec() {
            let mut x = v![3, 2, 1];
            x.sort();
            assert_eq!(vec![1, 2, 3], *x);
            let i = 1i32;
            assert_eq!(2, x[i]);
            x[i] = 3;
            assert_eq!(3, x[i]);
            let u = 1usize;
            assert_eq!(3, x[u]);
            x[u] = 2;
            assert_eq!(2, x[u]);
            assert_eq!(2, x[1]);

            assert_eq!("MyVec([1, 2, 3])", format!("{:?}", x));
            assert_eq!(v![1, 2, 3], x);

            assert_eq!("1\n2\n3", format!("{}", x));

            let mut y = v![v![1, 2]; 3];
            y[0][0] = 2;
            assert_eq!(vec![2, 2], *y[0]);
            assert_eq!(vec![1, 2], *y[1]);
        }
    }
}
//////////////////////////////// LIBRARY END ////////////////////////////////

use contest::io::Scanner;
use contest::prelude::MyVec;
use std::collections::BinaryHeap;

fn main() {
    let mut sc = Scanner::new(std::io::stdin());
    let n = sc.next::<i32>();
    let m = sc.next::<i32>();
    let q = sc.next::<i32>();
    let s = sc.next::<String>().chars().collect::<MyVec<char>>();
    let t = sc.next::<String>().chars().collect::<MyVec<char>>();

    let mut bottomLeft = v![-1; n];
    let mut bottomRight = v![-1; n];
    let mut upLeft = v![-1; n];
    let mut upRight = v![-1; n];
    for i in 0..n {
        if s[i] == 'W' {
            upLeft[i] = i;
            if i > 0 {
                upRight[i] = upRight[i - 1];
            }
        } else {
            upRight[i] = i;
            if i > 0 {
                upLeft[i] = upLeft[i - 1];
            }
        }
    }
    for i in (0..n).rev() {
        if s[i] == 'W' {
            bottomLeft[i] = i;
            if i + 1 < n {
                bottomRight[i] = bottomRight[i + 1];
            }
        } else {
            bottomRight[i] = i;
            if i + 1 < n {
                bottomLeft[i] = bottomLeft[i + 1];
            }
        }
    }

    let mut leftUp = v![-1; m];
    let mut leftDown = v![-1; m];
    let mut rightUp = v![-1; m];
    let mut rightDown = v![-1; m];
    for i in 0..m {
        if t[i] == 'N' {
            leftUp[i] = i;
            if i > 0 {
                leftDown[i] = leftDown[i - 1];
            }
        } else {
            leftDown[i] = i;
            if i > 0 {
                leftUp[i] = leftUp[i - 1];
            }
        }
    }
    for i in (0..m).rev() {
        if t[i] == 'N' {
            rightUp[i] = i;
            if i + 1 < m {
                rightDown[i] = rightDown[i + 1];
            }
        } else {
            rightDown[i] = i;
            if i + 1 < m {
                rightUp[i] = rightUp[i + 1];
            }
        }
    }

    for _ in 0..q {
        let a = sc.next::<i32>() - 1;
        let b = sc.next::<i32>() - 1;
        let c = sc.next::<i32>() - 1;
        let d = sc.next::<i32>() - 1;

        let mut rows = v![];
        let mut cols = v![];

        push(&mut rows, (upRight[a], 'R'));
        push(&mut rows, (upRight[a], 'R'));
        push(&mut rows, (upRight[c], 'R'));
        push(&mut rows, (bottomRight[a], 'R'));
        push(&mut rows, (bottomRight[c], 'R'));
        push(&mut rows, (upLeft[a], 'L'));
        push(&mut rows, (upLeft[c], 'L'));
        push(&mut rows, (bottomLeft[a], 'L'));
        push(&mut rows, (bottomLeft[c], 'L'));

        push(&mut cols, (leftUp[b], 'U'));
        push(&mut cols, (leftUp[d], 'U'));
        push(&mut cols, (rightUp[b], 'U'));
        push(&mut cols, (rightUp[d], 'U'));
        push(&mut cols, (leftDown[b], 'D'));
        push(&mut cols, (leftDown[d], 'D'));
        push(&mut cols, (rightDown[b], 'D'));
        push(&mut cols, (rightDown[d], 'D'));

        rows.sort();
        cols.sort();

        rows.dedup();
        cols.dedup();

        let mut startX = 10;
        let mut startY = 10;
        let mut goalX = 10;
        let mut goalY = 10;
        for i in 0..rows.len() {
            if rows[i].0 == a {
                startX = i;
            }
            if rows[i].0 == c {
                goalX = i;
            }
        }
        for i in 0..cols.len() {
            if cols[i].0 == b {
                startY = i;
            }
            if cols[i].0 == d {
                goalY = i;
            }
        }

        let inf = 1_000_000_000;
        let mut dist = v![v![inf; 8]; 8];
        let mut q = BinaryHeap::new();
        q.push((inf - 0, startX, startY));
        while !q.is_empty() {
            let (dd, x, y) = q.pop().unwrap();
            if dist[x][y] < inf {
                continue;
            }
            dist[x][y] = inf - dd;
            if rows[x].1 == 'L' {
                if y > 0 {
                    let d = cols[y].0 - cols[y - 1].0;
                    q.push((dd - d, x, y - 1));
                }
            } else {
                if y + 1 < cols.len() {
                    let d = cols[y + 1].0 - cols[y].0;
                    q.push((dd - d, x, y + 1));
                }
            }
            if cols[y].1 == 'U' {
                if x > 0 {
                    let d = rows[x].0 - rows[x - 1].0;
                    q.push((dd - d, x - 1, y));
                }
            } else {
                if x + 1 < rows.len() {
                    let d = rows[x + 1].0 - rows[x].0;
                    q.push((dd - d, x + 1, y));
                }
            }
        }
        let res = dist[goalX][goalY];
        if res == inf {
            println!("-1");
        } else {
            println!("{}", res);
        }
    }
}

fn push(rows: &mut Vec<(i32, char)>, (x, d): (i32, char)) {
    if x >= 0 {
        rows.push((x, d));
    }
}