Problem: Omkar has a pie tray with k (2 ≤ k ≤ 20) spots. Each spot in the tray contains either a chocolate pie or a pumpkin pie. However, Omkar does not like the way that the pies are currently arranged, and has another ideal arrangement that he would prefer instead.

To assist Omkar, n elves have gathered in a line to swap the pies in Omkar's tray. The j-th elf from the left is able to swap the pies at positions a_j and b_j in the tray.

In order to get as close to his ideal arrangement as possible, Omkar may choose a contiguous subsegment of the elves and then pass his pie tray through the subsegment starting from the left. However, since the elves have gone to so much effort to gather in a line, they request that Omkar's chosen segment contain at least m (1 ≤ m ≤ n) elves.

Formally, Omkar may choose two integers l and r satisfying 1 ≤ l ≤ r ≤ n and r - l + 1 ≥ m so that first the pies in positions a_l and b_l will be swapped, then the pies in positions a_{l + 1} and b_{l + 1} will be swapped, etc. until finally the pies in positions a_r and b_r are swapped.

Help Omkar choose a segment of elves such that the amount of positions in Omkar's final arrangement that contain the same type of pie as in his ideal arrangement is the maximum possible. Note that since Omkar has a big imagination, it might be that the amounts of each type of pie in his original arrangement and in his ideal arrangement do not match.

Input

The first line contains three integers n, m, and k (1 ≤ m ≤ n ≤ 10^6 and 2 ≤ k ≤ 20) — the number of elves, the minimum subsegment length, and the number of spots in Omkar's tray respectively. 

The second and third lines each contain a string of length k consisting of 0s and 1s that represent initial arrangement of pies and ideal arrangement of pies; the j-th character in each string is equal to 0 if the j-th spot in the arrangement contains a chocolate pie and is equal to 1 if the j-th spot in the arrangement contains a pumpkin pie. It is not guaranteed that the two strings have the same amount of 0s or the same amount of 1s.

n lines follow. The j-th of these lines contains two integers a_j and b_j (1 ≤ a_j, b_j ≤ k, a_j ≠ b_j) which indicate that the j-th elf from the left can swap the pies at positions a_j and b_j in the tray.

Output

Output two lines. 

The first line should contain a single integer s (0 ≤ s ≤ k) equal to the amount of positions that contain the same type of pie in Omkar's final arrangement and in Omkar's ideal arrangement; s should be the maximum possible. 

The second line should contain two integers l and r satisfying 1 ≤ l ≤ r ≤ n and r - l + 1 ≥ m, indicating that Omkar should pass his tray through the subsegment l, l + 1, ..., r to achieve a final arrangement with s positions having the same type of pie as his ideal arrangement.

If there are multiple answers you may output any of them.

Examples

Input


4 2 5
11000
00011
1 3
3 5
4 2
3 4


Output


5
1 3


Input


4 3 5
11000
00011
1 3
1 5
2 4
1 5


Output


3
1 4

Note

In the first test case, the swaps will go like this: 

  * Swap 1 and 3: 11000 becomes 01100
  * Swap 3 and 5: 01100 becomes 01001
  * Swap 4 and 2: 01001 becomes 00011

The final arrangement is the same as the ideal arrangement 00011, so there are 5 positions with the same type of pie, which is optimal.

In the second test case, the swaps will go like this: 

  * Swap 1 and 3: 11000 becomes 01100
  * Swap 1 and 5: 01100 becomes 01100
  * Swap 4 and 2: 01100 becomes 00110
  * Swap 1 and 5: 00110 becomes 00110

The final arrangement has 3 positions with the same type of pie as the ideal arrangement 00011, those being positions 1, 2, and 4. In this case the subsegment of elves (l, r) = (2, 3) is more optimal, but that subsegment is only length 2 and therefore does not satisfy the constraint that the subsegment be of length at least m = 3.

Solution (in JAVA):

Solution:
import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class cf1392g {

    public static void main(String[] args) throws IOException {
        int n = rni(), m = ni(), k = ni(), s[] = new int[n + 1], t[] = new int[n + 1], rev[][] = new int[n + 1][];
        s[0] = Integer.parseInt(rline(), 2);
        t[0] = Integer.parseInt(rline(), 2);
        rev[0] = identity(k);
        for (int i = 0; i < n; ++i) {
            int a = rni() - 1, b = ni() - 1;
            rev[i + 1] = reverse_apply(rev[i], a, b);
            s[i + 1] = apply(s[0], rev[i + 1]);
            t[i + 1] = apply(t[0], rev[i + 1]);
        }
        int left[] = new int[1 << k], right[] = new int[1 << k], ans = 0, anscnt = 0;
        fill(left, n + 1);
        fill(right, -1);
        for (int i = 0; i <= n; ++i) {
            left[s[i]] = min(left[s[i]], i);
            right[t[i]] = max(right[t[i]], i);
        }
        for (int i = (1 << k) - 1; i > 0; --i) {
            for (int j = 0; j < k; ++j) {
                if ((i & (1 << j)) > 0) {
                    left[i & ~(1 << j)] = min(left[i & ~(1 << j)], left[i]);
                    right[i & ~(1 << j)] = max(right[i & ~(1 << j)], right[i]);
                }
            }
        }
        for (int i = 0; i < 1 << k; ++i) {
            if (left[i] <= n && right[i] >= 0) {
                int cnt = cntmatch(s[left[i]], t[right[i]], k);
                // prln(Integer.toBinaryString(i) + ": ");
                // prln("\t" + Integer.toBinaryString(s[left[i]]));
                // prln("\t" + Integer.toBinaryString(t[right[i]]));
                // prln("\t" + cnt);
                if (right[i] - left[i] >= m && cnt > anscnt) {
                    anscnt = cnt;
                    ans = i;
                }
            }
        }
        if (anscnt == 0) {
            prln(0);
            prln(1, 1);
        } else {
            prln(anscnt);
            prln(left[ans] + 1, right[ans]);
        }
        close();
    }

    static int cntmatch(int s, int t, int n) {
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans += ~(s ^ t) & 1;
            s >>= 1;
            t >>= 1;
        }
        return ans;
    }

    static boolean subset(int s, int t) {
        while (s > 0) {
            if (((s & 1) | (~(s ^ t) & 1)) == 0) {
                return false;
            }
            s >>= 1;
            t >>= 1;
        }
        return t > 0;
    }

    static int apply(int s, int[] a) {
        int ans = 0;
        for (int i = 0; i < a.length; ++i) {
            ans |= ((s & (1 << (a.length - a[i] - 1))) > 0 ? 1 : 0) << (a.length - i - 1);
        }
        return ans;
    }

    static int[] reverse_apply(int[] t, int a, int b) {
        int[] ans = new int[t.length];
        for (int i = 0; i < t.length; ++i) {
            if (t[i] == a) {
                ans[i] = b;
            } else if (t[i] == b) {
                ans[i] = a;
            } else {
                ans[i] = t[i];
            }
        }
        return ans;
    }

    static int[] identity(int n) {
        int[] ans = new int[n];
        for (int i = 0; i < n; ++i) {
            ans[i] = i;
        }
        return ans;
    }

    static BufferedReader __in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter __out = new PrintWriter(new OutputStreamWriter(System.out));
    static StringTokenizer input;
    static Random __rand = new Random();

    // references
    // IBIG = 1e9 + 7
    // IMAX ~= 2e9
    // LMAX ~= 9e18
    
    // constants
    static final int IBIG = 1000000007;
    static final int IMAX = 2147483647;
    static final int IMIN = -2147483648;
    static final long LMAX = 9223372036854775807L;
    static final long LMIN = -9223372036854775808L;
    // math util
    static int minof(int a, int b, int c) {return min(a, min(b, c));}
    static int minof(int... x) {if(x.length == 1) return x[0]; if(x.length == 2) return min(x[0], x[1]); if(x.length == 3) return min(x[0], min(x[1], x[2])); int min = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] < min) min = x[i]; return min;}
    static long minof(long a, long b, long c) {return min(a, min(b, c));}
    static long minof(long... x) {if(x.length == 1) return x[0]; if(x.length == 2) return min(x[0], x[1]); if(x.length == 3) return min(x[0], min(x[1], x[2])); long min = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] < min) min = x[i]; return min;}
    static int maxof(int a, int b, int c) {return max(a, max(b, c));}
    static int maxof(int... x) {if(x.length == 1) return x[0]; if(x.length == 2) return max(x[0], x[1]); if(x.length == 3) return max(x[0], max(x[1], x[2])); int max = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] > max) max = x[i]; return max;}
    static long maxof(long a, long b, long c) {return max(a, max(b, c));}
    static long maxof(long... x) {if(x.length == 1) return x[0]; if(x.length == 2) return max(x[0], x[1]); if(x.length == 3) return max(x[0], max(x[1], x[2])); long max = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] > max) max = x[i]; return max;}
    static int powi(int a, int b) {if(a == 0) return 0; int ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static long powl(long a, int b) {if(a == 0) return 0; long ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static int fli(double d) {return (int)d;}
    static int cei(double d) {return (int)ceil(d);}
    static long fll(double d) {return (long)d;}
    static long cel(double d) {return (long)ceil(d);}
    static int gcf(int a, int b) {return b == 0 ? a : gcf(b, a % b);}
    static long gcf(long a, long b) {return b == 0 ? a : gcf(b, a % b);}
    static int lcm(int a, int b) {return a * b / gcf(a, b);}
    static long lcm(long a, long b) {return a * b / gcf(a, b);}
    static int randInt(int min, int max) {return __rand.nextInt(max - min + 1) + min;}
    static long hash(long x) {x += 0x9e3779b97f4a7c15L; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9L; x = (x ^ (x >> 27)) * 0x94d049bb133111ebL; return x ^ (x >> 31);}
    // array util
    static void reverse(int[] a) {for(int i = 0, n = a.length, half = n / 2; i < half; ++i) {int swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(long[] a) {for(int i = 0, n = a.length, half = n / 2; i < half; ++i) {long swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(double[] a) {for(int i = 0, n = a.length, half = n / 2; i < half; ++i) {double swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(char[] a) {for(int i = 0, n = a.length, half = n / 2; i < half; ++i) {char swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void shuffle(int[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); int swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(long[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); long swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(double[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); double swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void rsort(int[] a) {shuffle(a); sort(a);}
    static void rsort(long[] a) {shuffle(a); sort(a);}
    static void rsort(double[] a) {shuffle(a); sort(a);}
    static int[] copy(int[] a) {int[] ans = new int[a.length]; for(int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static long[] copy(long[] a) {long[] ans = new long[a.length]; for(int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static double[] copy(double[] a) {double[] ans = new double[a.length]; for(int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static char[] copy(char[] a) {char[] ans = new char[a.length]; for(int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    // graph util
    static List<List<Integer>> g(int n) {List<List<Integer>> g = new ArrayList<>(); for(int i = 0; i < n; ++i) g.add(new ArrayList<>()); return g;}
    static List<Set<Integer>> sg(int n) {List<Set<Integer>> g = new ArrayList<>(); for(int i = 0; i < n; ++i) g.add(new HashSet<>()); return g;}
    static void c(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).add(v); g.get(v).add(u);}
    static void cto(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).add(v);}
    static void dc(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).remove(v); g.get(v).remove(u);}
    static void dcto(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).remove(v);}
    // input
    static void r() throws IOException {input = new StringTokenizer(rline());}
    static int ri() throws IOException {return Integer.parseInt(rline());}
    static long rl() throws IOException {return Long.parseLong(rline());}
    static int[] ria(int n) throws IOException {int[] a = new int[n]; r(); for(int i = 0; i < n; ++i) a[i] = ni(); return a;}
    static int[] riam1(int n) throws IOException {int[] a = new int[n]; r(); for(int i = 0; i < n; ++i) a[i] = ni() - 1; return a;}
    static long[] rla(int n) throws IOException {long[] a = new long[n]; r(); for(int i = 0; i < n; ++i) a[i] = nl(); return a;}
    static char[] rcha() throws IOException {return rline().toCharArray();}
    static String rline() throws IOException {return __in.readLine();}
    static String n() {return input.nextToken();}
    static int rni() throws IOException {r(); return ni();}
    static int ni() {return Integer.parseInt(n());}
    static long rnl() throws IOException {r(); return nl();}
    static long nl() {return Long.parseLong(n());}
    static double rnd() throws IOException {r(); return nd();}
    static double nd() {return Double.parseDouble(n());}
    static List<List<Integer>> rg(int n, int m) throws IOException {List<List<Integer>> g = g(n); for(int i = 0; i < m; ++i) c(g, rni() - 1, ni() - 1); return g;}
    static void rg(List<List<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) c(g, rni() - 1, ni() - 1);}
    static List<List<Integer>> rdg(int n, int m) throws IOException {List<List<Integer>> g = g(n); for(int i = 0; i < m; ++i) cto(g, rni() - 1, ni() - 1); return g;}
    static void rdg(List<List<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) cto(g, rni() - 1, ni() - 1);}
    static List<Set<Integer>> rsg(int n, int m) throws IOException {List<Set<Integer>> g = sg(n); for(int i = 0; i < m; ++i) c(g, rni() - 1, ni() - 1); return g;}
    static void rsg(List<Set<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) c(g, rni() - 1, ni() - 1);}
    static List<Set<Integer>> rdsg(int n, int m) throws IOException {List<Set<Integer>> g = sg(n); for(int i = 0; i < m; ++i) cto(g, rni() - 1, ni() - 1); return g;}
    static void rdsg(List<Set<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) cto(g, rni() - 1, ni() - 1);}
    // output
    static void pr(int i) {__out.print(i);}
    static void prln(int i) {__out.println(i);}
    static void pr(long l) {__out.print(l);}
    static void prln(long l) {__out.println(l);}
    static void pr(double d) {__out.print(d);}
    static void prln(double d) {__out.println(d);}
    static void pr(char c) {__out.print(c);}
    static void prln(char c) {__out.println(c);}
    static void pr(char[] s) {__out.print(new String(s));}
    static void prln(char[] s) {__out.println(new String(s));}
    static void pr(String s) {__out.print(s);}
    static void prln(String s) {__out.println(s);}
    static void pr(Object o) {__out.print(o);}
    static void prln(Object o) {__out.println(o);}
    static void prln() {__out.println();}
    static void pryes() {__out.println("yes");}
    static void pry() {__out.println("Yes");}
    static void prY() {__out.println("YES");}
    static void prno() {__out.println("no");}
    static void prn() {__out.println("No");}
    static void prN() {__out.println("NO");}
    static void pryesno(boolean b) {__out.println(b ? "yes" : "no");};
    static void pryn(boolean b) {__out.println(b ? "Yes" : "No");}
    static void prYN(boolean b) {__out.println(b ? "YES" : "NO");}
    static void prln(int... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static void prln(long... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static void prln(double... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static <T> void prln(Collection<T> c) {int n = c.size() - 1; Iterator<T> iter = c.iterator(); for(int i = 0; i < n; __out.print(iter.next()), __out.print(' '), ++i); if(n >= 0) __out.println(iter.next()); else __out.println();}
    static void h() {__out.println("hlfd"); flush();}
    static void flush() {__out.flush();}
    static void close() {__out.close();}
}