#include <bits/stdc++.h>
using namespace std;

const long long MOD = 1000000007;

typedef long long
    ll;  // -9,223,372,036,854,775,808 から 9,223,372,036,854,775,807

template <class T>
using vec = std::vector<T>;
template <class T>
using vec2 = vec<vec<T>>;
template <class T>
using vec3 = vec<vec<vec<T>>>;

// #define DEBUG

struct GCDResult {
    long long x;
    long long y;
    long long res;
};
GCDResult gcd(long long a, long long b) {
    if (a < 0) {
        auto sub = gcd(-a, b);
        return GCDResult{-sub.x, sub.y, sub.res};
    }
    if (b < 0) {
        auto sub = gcd(a, -b);
        return GCDResult{sub.x, -sub.y, sub.res};
    }
    if (a < b) {
        auto sub = gcd(b, a);
        return GCDResult{sub.y, sub.x, sub.res};
    }
    // a >= b AND a >= 0 AND b >= 0
    if (b == 0) {
        return GCDResult{1LL, 0LL, a};
    }
    // a >= b AND a > 0 AND b > 0
    auto sub = gcd(b, a % b);
    return GCDResult{sub.y, sub.x - sub.y * (a / b), sub.res};
}

// Requires ATC_GCD
const int COM_MAX = 510000;
template <long long p>
class Zp {
    long long content;

    // for comb()
    static array<long long, COM_MAX> fac;
    static array<long long, COM_MAX> finv;
    static array<long long, COM_MAX> inv_;
    static bool is_initialized_com_table;

    // By rng_2 (See https://drken1215.hatenablog.com/entry/2018/06/08/210000)
    // テーブルを作る前処理
    static void COMinit() {
        auto MOD = p;
        auto MAX = COM_MAX;
        fac[0] = fac[1] = 1;
        finv[0] = finv[1] = 1;
        inv_[1] = 1;
        for (int i = 2; i < MAX; i++) {
            fac[i] = fac[i - 1] * i % MOD;
            inv_[i] = MOD - inv_[MOD % i] * (MOD / i) % MOD;
            finv[i] = finv[i - 1] * inv_[i] % MOD;
        }
        is_initialized_com_table = true;
    }

    // 二項係数計算
    static long long COM(int n, int k) {
        auto MOD = p;
        auto MAX = COM_MAX;
        if (!is_initialized_com_table) {
            assert(false);
        }
        if (n < k) return 0;
        if (n < 0 || k < 0) return 0;
        return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
    }

   public:
    Zp(long long content_) {
        if (content_ >= 0) {
            content = content_ % p;
        } else {
            long long temp = p;
            while (temp < -content_) {
                temp *= p;
            }
            content = (temp + content_) % p;
        }
    }

    bool operator==(const Zp<p>& rhs) const {
        return this->content == rhs.content;
    }

    bool operator!=(const Zp<p>& rhs) const { return !(*this == rhs); }

    Zp<p> operator+(const Zp<p>& rhs) const {
        return Zp<p>(this->content + rhs.content);
    }

    Zp<p> operator-() const { return Zp<p>(p - this->content); }

    Zp<p> operator-(const Zp<p>& rhs) const {
        return Zp<p>(this->content - rhs.content + p);
    }

    Zp<p> operator*(const Zp<p>& rhs) const {
        return Zp<p>(this->content * rhs.content);
    }

    Zp<p> inv() const {
        if (this->content == 0) {
            assert(false);
        }

        auto res = gcd(this->content, p);
        return Zp<p>(res.x);
    }

    Zp<p> operator/(const Zp<p>& rhs) const {
        if (rhs.content == 0) {
            assert(false);
        }

        return (*this) * rhs.inv();
    }

    Zp<p> pow(int n) {
        auto res = Zp<p>(1);
        Zp<p> mult = (*this);
        while (n > 0) {
            if (n & 1 == 1) {
                res = res * mult;
            }
            n >>= 1;
            mult = mult * mult;
        }
        return res;
    }

    long long raw() { return this->content; }

    static void initializeCom() { COMinit(); }

    static Zp<p> com(int n, int k) { return Zp<p>(COM(n, k)); }
};

template <long long p>
bool Zp<p>::is_initialized_com_table = false;
template <long long p>
array<long long, COM_MAX> Zp<p>::fac;
template <long long p>
array<long long, COM_MAX> Zp<p>::finv;
template <long long p>
array<long long, COM_MAX> Zp<p>::inv_;

void solve(long long N, long long M, std::vector<long long> S,
           std::vector<long long> T) {
    vec2<Zp<MOD>> table(M + 1, vec<Zp<MOD>>(N + 1, Zp<MOD>(0)));
    table.at(0).at(0) = Zp<MOD>(1);

    for (int i = 1; i < M + 1; i++) {
        table.at(i).at(0) = Zp<MOD>(1);
        vec<Zp<MOD>> psums(N + 1, Zp<MOD>(0));
        psums.at(0) = Zp<MOD>(1);
        for(int j=1; j < N + 1; j++){
            psums.at(j) = psums.at(j-1) + table.at(i-1).at(j);
        }
        for (int j = 1; j < N + 1; j++) {
            if (T.at(i - 1) == S.at(j - 1)) {
                Zp<MOD> psum = psums.at(j-1);
                // for (int k = 0; k <= j - 1; k++) {
                //     psum = psum + table.at(i - 1).at(k);
                // }
                table.at(i).at(j) = psum;
            }
            table.at(i).at(j) = table.at(i).at(j) + table.at(i - 1).at(j);
        }
    }

#ifdef DEBUG
    printf("*START: hoge\n");
    for (int i = 0; i < table.size(); i++) {
        for (int j = 0; j < table[0].size(); j++) {
            cout << table[i][j].raw() << "\t";
        }
        cout << endl;
    }
    printf("*END: hoge\n");
#endif

    Zp<MOD> res();

    cout << accumulate(table.back().begin(), table.back().end(), Zp<MOD>(0))
                .raw()
         << endl;
}

// Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You
// use the default template now. You can remove this line by using your custom
// template)
int main() {
    long long N;
    scanf("%lld", &N);
    long long M;
    scanf("%lld", &M);
    std::vector<long long> S(N);
    for (int i = 0; i < N; i++) {
        scanf("%lld", &S[i]);
    }
    std::vector<long long> T(M);
    for (int i = 0; i < M; i++) {
        scanf("%lld", &T[i]);
    }
    solve(N, M, std::move(S), std::move(T));
    return 0;
}


Measured memory_bytes: 31616