Problem: Tachibana Kanade likes Mapo Tofu very much. One day, the canteen cooked all kinds of tofu to sell, but not all tofu is Mapo Tofu, only those spicy enough can be called Mapo Tofu.

Each piece of tofu in the canteen is given a m-based number, all numbers are in the range [l, r] (l and r being m-based numbers), and for every m-based integer in the range [l, r], there exists a piece of tofu with that number.

To judge what tofu is Mapo Tofu, Tachibana Kanade chose n m-based number strings, and assigned a value to each string. If a string appears in the number of a tofu, the value of the string will be added to the value of that tofu. If a string appears multiple times, then the value is also added that many times. Initially the value of each tofu is zero.

Tachibana Kanade considers tofu with values no more than k to be Mapo Tofu. So now Tachibana Kanade wants to know, how many pieces of tofu are Mapo Tofu?

Input

The first line contains three integers n, m and k (1 ≤ n ≤ 200; 2 ≤ m ≤ 20; 1 ≤ k ≤ 500). Where n denotes the number of strings, m denotes the base used, and k denotes the limit of the value for Mapo Tofu.

The second line represents the number l. The first integer in the line is len (1 ≤ len ≤ 200), describing the length (number of digits in base m) of l. Then follow len integers a1, a2, ..., alen (0 ≤ ai < m; a1 > 0) separated by spaces, representing the digits of l, with a1 being the highest digit and alen being the lowest digit.

The third line represents the number r in the same format as l. It is guaranteed that 1 ≤ l ≤ r.

Then follow n lines, each line describing a number string. The i-th line contains the i-th number string and vi — the value of the i-th string (1 ≤ vi ≤ 200). All number strings are described in almost the same format as l, the only difference is number strings may contain necessary leading zeros (see the first example). The sum of the lengths of all number strings does not exceed 200.

Output

Output the number of pieces of Mapo Tofu modulo 1000000007 (109 + 7). The answer should be a decimal integer.

Examples

Input

2 10 1
1 1
3 1 0 0
1 1 1
1 0 1


Output

97


Input

2 10 12
2 5 9
6 6 3 5 4 9 7
2 0 6 1
3 6 7 2 1


Output

635439


Input

4 2 6
6 1 0 1 1 1 0
6 1 1 0 1 0 0
1 1 2
3 0 1 0 5
4 0 1 1 0 4
3 1 0 1 2


Output

2

Note

In the first sample, 10, 11 and 100 are the only three decimal numbers in [1, 100] with a value greater than 1. Here the value of 1 is 1 but not 2, since numbers cannot contain leading zeros and thus cannot be written as "01".

In the second sample, no numbers in the given interval have a value greater than 12.

In the third sample, 110000 and 110001 are the only two binary numbers in the given interval with a value no greater than 6.

Solution (in JAVA):

Solution:
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 29);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            CTachibanaKanadesTofu solver = new CTachibanaKanadesTofu();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class CTachibanaKanadesTofu {
        int[][] next;
        int[] stateVal;
        int[] l;
        int[] r;
        int[][][][][][] dp;
        int mod = (int) 1e9 + 7;
        int m;

        public int[] readString(FastInput in) {
            int n = in.ri();
            int[] a = in.ri(n);
            SequenceUtils.reverse(a);
            return a;
        }

        public int dp(int floor, int ceil, int begin, int remain, int state, int digit) {
            if (digit < 0) {
                return 1;
            }
            if (dp[floor][ceil][begin][remain][state][digit] == -1) {
                long sum = 0;
                for (int j = 0; j < m; j++) {
                    if (ceil == 1 && j > r[digit]) {
                        continue;
                    }
                    if (floor == 1 && j < l[digit]) {
                        continue;
                    }
                    int to = j == 0 && begin == 0 ? 0 : next[j][state];
                    if (stateVal[to] > remain) {
                        continue;
                    }
                    sum += dp(floor == 1 && j == l[digit] ? 1 : 0,
                            ceil == 1 && j == r[digit] ? 1 : 0,
                            begin == 0 && j == 0 ? 0 : 1,
                            remain - stateVal[to],
                            to,
                            digit - 1);
                }
                sum %= mod;
                dp[floor][ceil][begin][remain][state][digit] = (int) sum;
            }
            return dp[floor][ceil][begin][remain][state][digit];
        }

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.ri();
            m = in.ri();
            int k = in.ri();
            l = readString(in);
            r = readString(in);
            if (l.length < r.length) {
                l = Arrays.copyOf(l, r.length);
            }
            AhoCorasick ac = new AhoCorasick(0, m - 1, 2000);
            int[] stringVal = new int[n];
            int[] endNode = new int[n];
            for (int i = 0; i < n; i++) {
                int len = in.ri();
                ac.prepareBuild();
                for (int j = 0; j < len; j++) {
                    ac.build(in.ri());
                }
                endNode[i] = ac.buildLast;
                stringVal[i] = in.ri();
            }
            int[] topo = ac.endBuild();
            next = ac.next;
            stateVal = new int[topo.length];
            for (int i = 0; i < n; i++) {
                stateVal[endNode[i]] += stringVal[i];
            }
            for (int i = 1; i < topo.length; i++) {
                int node = topo[i];
                stateVal[node] += stateVal[ac.fails[node]];
            }

            dp = new int[2][2][2][k + 1][topo.length][r.length];
            SequenceUtils.deepFill(dp, -1);

            int ans = dp(1, 1, 0, k, 0, r.length - 1);
            out.println(ans);
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        public void populate(int[] data) {
            for (int i = 0; i < data.length; i++) {
                data[i] = readInt();
            }
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int ri() {
            return readInt();
        }

        public int[] ri(int n) {
            int[] ans = new int[n];
            populate(ans);
            return ans;
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class AhoCorasick {
        public int[][] next;
        public int[] fails;
        private int minChar;
        private int maxChar;
        private int allocIndicator;
        private int range;
        public int buildLast;

        public void init() {
            allocIndicator = 1;
        }

        private int alloc() {
            return allocIndicator++;
        }

        public AhoCorasick(int minChar, int maxChar, int cap) {
            this.minChar = minChar;
            this.maxChar = maxChar;
            range = maxChar - minChar + 1;
            next = new int[range][cap + 1];
            fails = new int[cap + 1];
            init();
        }

        public void prepareBuild() {
            buildLast = 0;
        }

        public void build(int c) {
            c -= minChar;
            if (next[c][buildLast] == 0) {
                next[c][buildLast] = alloc();
            }
            buildLast = next[c][buildLast];
        }

        public int[] endBuild() {
            int[] dq = new int[allocIndicator];
            int dqTail = 1;
            int dqHead = 1;
            fails[0] = -1;
            for (int i = 0; i < range; i++) {
                if (next[i][0] != 0) {
                    dq[dqTail++] = next[i][0];
                    fails[next[i][0]] = 0;
                }
            }

            while (dqHead < dqTail) {
                int head = dq[dqHead++];
                for (int i = 0; i < range; i++) {
                    if (next[i][head] != 0) {
                        dq[dqTail++] = next[i][head];
                        int fail = visit(fails[head], i);
                        if (fail == -1) {
                            fail = 0;
                        } else {
                            fail = next[i][fail];
                        }
                        fails[next[i][head]] = fail;
                    }
                }
            }

            dqTail = 1;
            dqHead = 1;
            for (int i = 0; i < range; i++) {
                if (next[i][0] != 0) {
                    dq[dqTail++] = next[i][0];
                }
            }
            while (dqHead < dqTail) {
                int head = dq[dqHead++];
                for (int i = 0; i < range; i++) {
                    if (next[i][head] != 0) {
                        dq[dqTail++] = next[i][head];
                    } else {
                        next[i][head] = next[i][fails[head]];
                    }
                }
            }

            assert dqTail == allocIndicator;
            return dq;
        }

        public int visit(int trace, int index) {
            while (trace != -1 && next[index][trace] == 0) {
                trace = fails[trace];
            }
            return trace;
        }

    }

    static class SequenceUtils {
        public static void swap(int[] data, int i, int j) {
            int tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }

        public static void deepFill(Object array, int val) {
            if (!array.getClass().isArray()) {
                throw new IllegalArgumentException();
            }
            if (array instanceof int[]) {
                int[] intArray = (int[]) array;
                Arrays.fill(intArray, val);
            } else {
                Object[] objArray = (Object[]) array;
                for (Object obj : objArray) {
                    deepFill(obj, val);
                }
            }
        }

        public static void reverse(int[] data, int l, int r) {
            while (l < r) {
                swap(data, l, r);
                l++;
                r--;
            }
        }

        public static void reverse(int[] data) {
            reverse(data, 0, data.length - 1);
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private static final int THRESHOLD = 32 << 10;
        private final Writer os;
        private StringBuilder cache = new StringBuilder(THRESHOLD * 2);

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        private void afterWrite() {
            if (cache.length() < THRESHOLD) {
                return;
            }
            flush();
        }

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput append(char c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(int c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput println(int c) {
            return append(c).println();
        }

        public FastOutput println() {
            return append('\n');
        }

        public FastOutput flush() {
            try {
//            boolean success = false;
//            if (stringBuilderValueField != null) {
//                try {
//                    char[] value = (char[]) stringBuilderValueField.get(cache);
//                    os.write(value, 0, cache.length());
//                    success = true;
//                } catch (Exception e) {
//                }
//            }
//            if (!success) {
                os.append(cache);
//            }
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }
}