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 Training20200528.Questions;
using Training20200528.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Training20200528.Questions
{
    public class QuestionE : AtCoderQuestionBase
    {
        public override IEnumerable<object> Solve(TextReader inputStream)
        {
            var nm = inputStream.ReadIntArray();
            var s = inputStream.ReadIntArray();
            var t = inputStream.ReadIntArray();

            var countSum = new BinaryIndexedTree2D(s.Length, t.Length);

            for (int row = 0; row < countSum.Height; row++)
            {
                for (int column = 0; column < countSum.Width; column++)
                {
                    if (s[row] == t[column])
                    {
                        countSum.AddAt(row, column, countSum.Sum(row, column) + 1);
                    }
                }
            }

            yield return (countSum.Sum(countSum.Height, countSum.Width) + 1) % 1000000007;
        }

        public class BinaryIndexedTree2D
        {
            long[,] _data;
            public int Height { get; }
            public int Width { get; }

            public BinaryIndexedTree2D(int height, int width)
            {
                Height = height;
                Width = width;
                _data = new long[height + 1, width + 1];
            }

            /// <summary>
            /// 2次元BITの[<c>row</c>, <c>column</c>]に<c>value</c>を足します。
            /// </summary>
            /// <param name="row">加算する行（0-indexed）</param>
            /// <param name="column">加算する列（0-indexed）</param>
            /// <param name="value">加算する値</param>
            public void AddAt(int row, int column, long value)
            {
                unchecked
                {
                    if ((ulong)row >= (ulong)Height)
                    {
                        throw new ArgumentOutOfRangeException(nameof(row));
                    }
                    if ((ulong)column >= (ulong)Width)
                    {
                        throw new ArgumentOutOfRangeException(nameof(column));
                    }
                }

                row++;    // 1-indexed
                column++;

                for (int i = row; i <= Height; i += i & -i)
                {
                    for (int j = column; j <= Width; j += j & -j)
                    {
                        _data[i, j] += value;
                        if (_data[i, j] >= 1000000007)
                        {
                            _data[i, j] -= 1000000007;
                        }
                    }
                }
            }

            /// <summary>
            /// 指定した半開区間の部分和を返します。
            /// </summary>
            /// <param name="row"></param>
            /// <param name="column"></param>
            /// <returns></returns>
            public long Sum(int row, int column)
            {
                long sum = 0;
                unchecked
                {
                    if ((ulong)row >= (ulong)(Height + 1))
                    {
                        throw new ArgumentOutOfRangeException(nameof(row));
                    }
                    if ((ulong)column >= (ulong)(Width + 1))
                    {
                        throw new ArgumentOutOfRangeException(nameof(column));
                    }
                }

                for (int i = row; i > 0; i -= i & -i)
                {
                    for (int j = column; j > 0; j -= j & -j)
                    {
                        sum += _data[i, j];
                    }
                }
                return sum % 1000000007;
            }
        }
    }
}


namespace Training20200528
{
    class Program
    {
        static void Main(string[] args)
        {
            IAtCoderQuestion question = new QuestionE();    // 問題に合わせて書き換え
            var answers = question.Solve(Console.In);
            foreach (var answer in answers)
            {
                Console.WriteLine(answer);
            }
        }
    }
}

#region Base Classes

namespace Training20200528.Questions
{

    public interface IAtCoderQuestion
    {
        IEnumerable<object> Solve(string input);
        IEnumerable<object> Solve(TextReader inputStream);
    }

    public abstract class AtCoderQuestionBase : IAtCoderQuestion
    {
        public IEnumerable<object> Solve(string input)
        {
            var stream = new MemoryStream(Encoding.Unicode.GetBytes(input));
            var reader = new StreamReader(stream, Encoding.Unicode);

            return Solve(reader);
        }

        public abstract IEnumerable<object> Solve(TextReader inputStream);
    }

}

#endregion

#region Extensions

namespace Training20200528.Extensions
{
    internal static class TextReaderExtensions
    {
        internal static int ReadInt(this TextReader reader) => int.Parse(ReadString(reader));
        internal static long ReadLong(this TextReader reader) => long.Parse(ReadString(reader));
        internal static double ReadDouble(this TextReader reader) => double.Parse(ReadString(reader));
        internal static string ReadString(this TextReader reader) => reader.ReadLine();

        internal static int[] ReadIntArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(int.Parse).ToArray();
        internal static long[] ReadLongArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(long.Parse).ToArray();
        internal static double[] ReadDoubleArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(double.Parse).ToArray();
        internal static string[] ReadStringArray(this TextReader reader, char separator = ' ') => reader.ReadLine().Split(separator);
    }
}

#endregion