Problem:
Score : 500 points

Problem Statement

You are given two integer sequences S and T of length N and M, respectively, both consisting of integers between 1 and 10^5 (inclusive).

In how many pairs of a subsequence of S and a subsequence of T do the two subsequences are the same in content?

Here the subsequence of A is a sequence obtained by removing zero or more elements from A and concatenating the remaining elements without changing the order.

For both S and T, we distinguish two subsequences if the sets of the indices of the removed elements are different, even if the subsequences are the same in content.

Since the answer can be tremendous, print the number modulo 10^9+7.

Constraints

1 \leq N, M \leq 2 \times 10^3

The length of S is N.

The length of T is M.

1 \leq S_i, T_i \leq 10^5

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
S_1 S_2 ... S_{N-1} S_{N}
T_1 T_2 ... T_{M-1} T_{M}

Output

Print the number of pairs of a subsequence of S and a subsequence of T such that the subsequences are the same in content, modulo 10^9+7.

Sample Input 1

2 2
1 3
3 1

Sample Output 1

3

S has four subsequences: (), (1), (3), (1, 3).

T has four subsequences: (), (3), (1), (3, 1).

There are 1 \times 1 pair of subsequences in which the subsequences are both (), 1 \times 1 pair of subsequences in which the subsequences are both (1), and 1 \times 1 pair of subsequences in which the subsequences are both (3), for a total of three pairs.

Sample Input 2

2 2
1 1
1 1

Sample Output 2

6

S has four subsequences: (), (1), (1), (1, 1).

T has four subsequences: (), (1), (1), (1, 1).

There are 1 \times 1 pair of subsequences in which the subsequences are both (), 2 \times 2 pairs of subsequences in which the subsequences are both (1), and 1 \times 1 pair of subsequences in which the subsequences are both (1,1), for a total of six pairs.
Note again that we distinguish two subsequences if the sets of the indices of the removed elements are different, even if the subsequences are the same in content.

Sample Input 3

4 4
3 4 5 6
3 4 5 6

Sample Output 3

16

Sample Input 4

10 9
9 6 5 7 5 9 8 5 6 7
8 6 8 5 5 7 9 9 7

Sample Output 4

191

Sample Input 5

20 20
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Sample Output 5

846527861

Be sure to print the number modulo 10^9+7.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;

namespace Contest
{
    class Program
    {
        static void Main(string[] args)
        {
            ABC130.E();
        }
        class ABC130
        {
            public static void A()
            {
                Console.WriteLine(Read.Int() < Read.Int() ? 0 : 10);
            }
            public static void B()
            {
                var N = Read.Int();
                var X = Read.Int();
                var L = Read.LongN();
                var D = Util.ASum(L);
                Console.WriteLine(D.Count(x => x <= X));
            }
            public static void C()
            {
                var W = Read.Long();
                var H = Read.Long();
                var x = Read.Long();
                var y = Read.Long();
                bool isCenter = W == x * 2 && H == y * 2;
                Console.WriteLine("{0} {1}", 1.0 * H * W / 2, isCenter ? 1 : 0);
            }
            public static void D()
            {
                var N = Read.Int();
                var K = Read.Long();
                var A = Read.LongN();
                long count = 0;
                int right = 0;
                long total = 0;
                for(int left = 0; left < N; ++left)
                {
                    while (right < N && total + A[right] < K)
                    {
                        total += A[right];
                        right++;
                    }
                    count += right - left;
                    if (left == right)
                    {
                        right++;
                    }
                    else
                    {
                        total -= A[left];
                    }
                }
                Console.WriteLine((long)N * (N + 1) / 2 - count);
            }
            public static void E()
            {
                var N = Read.Int();
                var M = Read.Int();
                var S = Read.IntN();
                var T = Read.IntN();
                var dp1 = new long[N + 1, M + 1];
                var dp2 = new long[N + 1, M + 1];
                for (int i = 0; i < N; ++i)
                {
                    for (int j = 0; j < M; ++j)
                    {
                        dp1[i + 1, j + 1] = S[i] == T[j] ? dp2[i, j] + 1 : 0;
                        dp2[i + 1, j + 1] = (dp2[i + 1, j] + dp2[i, j + 1] - dp2[i, j] + dp1[i + 1, j + 1] + Util.P) % Util.P;
                    }
                }
                Console.WriteLine(dp2[N, M] + 1);
            }
            public static void F()
            {
                var N = Read.Int();
                //List<double> X = new List<double>();
                //List<double> Y = new List<double>();
                //List<string> D = new List<string>();
                //for(int i = 0; i < N; ++i)
                //{
                //    var s = Read.StrN();
                //    X.Add(Convert.ToDouble(s[0]));
                //    Y.Add(Convert.ToDouble(s[1]));
                //    D.Add(s[2]);
                //}
                double maxX_UD = Double.MinValue, minX_UD = Double.MaxValue, maxX_L = Double.MinValue, minX_L = Double.MaxValue, maxX_R = Double.MinValue, minX_R = Double.MaxValue;
                double maxY_LR = Double.MinValue, minY_LR = Double.MaxValue, maxY_D = Double.MinValue, minY_D = Double.MaxValue, maxY_U = Double.MinValue, minY_U = Double.MaxValue;
                for (int i = 0; i < N; ++i)
                {
                    var s = Read.StrN();
                    var x  =Convert.ToDouble(s[0]);
                    var y = Convert.ToDouble(s[1]);
                    switch (s[2])
                    {
                        case "U":
                            maxX_UD = Math.Max(maxX_UD, x);
                            minX_UD = Math.Min(minX_UD, x);
                            maxY_U = Math.Max(maxY_U, y);
                            minY_U = Math.Max(minY_U, y);
                            break;
                        case "D":
                            maxX_UD = Math.Max(maxX_UD, x);
                            minX_UD = Math.Min(minX_UD, x);
                            maxY_D = Math.Max(maxY_D, y);
                            minY_D = Math.Max(minY_D, y);
                            break;
                        case "L":
                            maxX_L = Math.Max(maxX_L, x);
                            minX_L = Math.Min(minX_L, x);
                            maxY_LR = Math.Max(maxY_LR, y);
                            minY_LR = Math.Min(minY_LR, y);
                            break;
                        case "R":
                            maxX_R = Math.Max(maxX_R, x);
                            minX_R = Math.Min(minX_R, x);
                            maxY_LR = Math.Max(maxY_LR, y);
                            minY_LR = Math.Min(minY_LR, y);
                            break;
                    }
                }
                List<double> candidate = new List<double>();
                candidate.Add(0);
                candidate.Add(maxX_L - maxX_UD);
                candidate.Add(maxX_L - minX_UD);
                candidate.Add(minX_L - maxX_UD);
                candidate.Add(minX_L - minX_UD);
                candidate.Add(maxX_UD - maxX_R);
                candidate.Add(minX_UD - maxX_R);
                candidate.Add(maxX_UD - minX_R);
                candidate.Add(minX_UD - minX_R);
                candidate.Add((maxX_L - maxX_R) / 2);
                candidate.Add((minX_L - minX_R) / 2);
                candidate.Add(maxY_D - maxY_LR);
                candidate.Add(maxY_D - minY_LR);
                candidate.Add(minY_D - maxY_LR);
                candidate.Add(minY_D - minY_LR);
                candidate.Add(maxY_LR - maxY_U);
                candidate.Add(minY_LR - maxY_U);
                candidate.Add(maxY_LR - minY_U);
                candidate.Add(minY_LR - minY_U);
                candidate.Add((maxY_D - maxY_U) / 2);
                candidate.Add((minY_D - minY_U) / 2);
                candidate = candidate.Distinct().Where(x => x >= 0 && x < 1e9).ToList();
                double min = Double.MaxValue;
                foreach(var t in candidate)
                {
                    double maxX = Math.Max(maxX_UD, Math.Max(maxX_L - t, maxX_R + t));
                    double minX = Math.Min(minX_UD, Math.Min(minX_L - t, minX_R + t));
                    double maxY = Math.Max(maxY_LR, Math.Max(maxY_D - t, maxY_U + t));
                    double minY = Math.Min(minY_LR, Math.Min(minY_D - t, minY_U + t));
                    double v = (maxX - minX) * (maxY - minY);
                    min = Math.Min(min, v);
                }
                Console.WriteLine(min);
            }
        }

        class Util
        {
            public static readonly long P = 1000000007;
            public static long[] ASum(long[] array)
            {
                var res = new long[array.Length + 1];
                for (int i = 0; i < array.Length; ++i)
                {
                    res[i + 1] = res[i] + array[i];
                }
                return res;
            }

        }

        static class Read
        {
            static Queue<string> queue = new Queue<string>();
            static void Enqueue() { var ss = Console.ReadLine().Split(' '); foreach (var s in ss) { queue.Enqueue(s); } }
            public static int Int() { if (queue.Count == 0) { Enqueue(); } return Convert.ToInt32(queue.Dequeue()); }
            public static long Long() { if (queue.Count == 0) { Enqueue(); } return Convert.ToInt64(queue.Dequeue()); }
            public static string Str() { if (queue.Count == 0) { Enqueue(); } return queue.Dequeue(); }
            public static int[] IntN() { return Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray(); }
            public static long[] LongN() { return Console.ReadLine().Split(' ').Select(s => Convert.ToInt64(s)).ToArray(); }
            public static string[] StrN() { return Console.ReadLine().Split(' '); }
            public static Tuple<int, int>[] TupleInt(int n) { List<Tuple<int, int>> list = new List<Tuple<int, int>>(); for (int i = 0; i < n; ++i) { var ab = Read.IntN(); list.Add(new Tuple<int, int>(ab[0], ab[1])); } return list.ToArray(); }
            public static Tuple<long, long>[] TupleLong(int n) { List<Tuple<long, long>> list = new List<Tuple<long, long>>(); for (int i = 0; i < n; ++i) { var ab = Read.LongN(); list.Add(new Tuple<long, long>(ab[0], ab[1])); } return list.ToArray(); }
            public static Tuple<string, string>[] TupleStr(int n) { List<Tuple<string, string>> list = new List<Tuple<string, string>>(); for (int i = 0; i < n; ++i) { var ab = Read.StrN(); list.Add(new Tuple<string, string>(ab[0], ab[1])); } return list.ToArray(); }
            public static Tuple<double, double>[] TupleDouble(int n) { List<Tuple<double, double>> list = new List<Tuple<double, double>>(); for (int i = 0; i < n; ++i) { var ab = Read.LongN(); list.Add(new Tuple<double, double>(ab[0], ab[1])); } return list.ToArray(); }
            public static long[,] LongMatrix(int r, int c)
            {
                var mat = new long[r, c];
                for (int i = 0; i < r; ++i)
                {
                    var x = Read.LongN();
                    for (int j = 0; j < c; ++j)
                    {
                        mat[i, j] = x[j];
                    }
                }
                return mat;
            }
            public static Dictionary<int, HashSet<int>> AdjacencyList(int N, int M)
            {
                Dictionary<int, HashSet<int>> dict = new Dictionary<int, HashSet<int>>();
                for (int i = 0; i <= N; ++i)
                {
                    dict.Add(i, new HashSet<int>());
                }
                for (int i = 0; i < M; ++i)
                {
                    var ab = Read.IntN();
                    dict[ab[0]].Add(ab[1]);
                    dict[ab[1]].Add(ab[0]);
                }
                return dict;
            }
            public static Dictionary<int, Dictionary<int, long>> AdjacencyListWithWeight(int N, int M)
            {
                Dictionary<int, Dictionary<int, long>> dict = new Dictionary<int, Dictionary<int, long>>();
                for (int i = 0; i <= N; ++i)
                {
                    dict.Add(i, new Dictionary<int, long>());
                }
                for (int i = 0; i < M; ++i)
                {
                    var ab = Read.IntN();
                    dict[ab[0]].Add(ab[1], ab[2]);
                    dict[ab[1]].Add(ab[0], ab[2]);
                }
                return dict;
            }
        }
    }
}