#pragma once
#include <stdio.h>
#include <sstream>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <utility>
#include <set>
#include <cctype>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <limits>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define bit(x,v) ((ll)x << v)

const ll INF = 1000000007;
const int MAX = 210000;
const int MOD = 1000000007;

long long fac[MAX], finv[MAX], inv[MAX];
void COMinit() {
	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;
	}
}

// 二項係数計算
long long COM(int n, int k) {
	if (n < k) return 0;
	if (n < 0 || k < 0) return 0;
	return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

ll gcd(ll a, ll b) {
	if (b == 0) return a;
	return gcd(b, a % b);
}
int pr[100010];
void uini(int n) {
	for (size_t i = 0; i <= n; i++)
	{
		pr[i] = i;
	}
}

int parent(int x) {
	if (x == pr[x]) return x;
	return pr[x] = parent(pr[x]);
}

bool unit(int x, int y) {
	int px = parent(x);
	int py = parent(y);

	if (px == py) return false;
	if (px < py) {
		pr[py] = px;
	}
	else {
		pr[px] = py;
	}
	return true;
}

// res[i][c] := i 文字目以降で最初に文字 c が登場する index (存在しないときは n)
vector<vector<int> > calcNext(const string& S) {
	int n = (int)S.size();
	vector<vector<int> > res(n + 1, vector<int>(26, n));
	for (int i = n - 1; i >= 0; --i) {
		for (int j = 0; j < 26; ++j) res[i][j] = res[i + 1][j];
		res[i][S[i] - 'a'] = i;
	}
	return res;
}
// mod 1000000007 の世界で a += b する関数
void add(long long& a, long long b) {
	a += b;
	if (a >= MOD) a -= MOD;
}

ll f(ll b, ll n) {
	if (b > n) return n;
	return f(b, n / b) + (n % b);
}
ll xa[3];
ll xr[3];
ll xb[3];
bool use1[3];
ll Cb(ll n, vector<ll> vec, int de);
ll Ca(ll n, vector<ll> vec, int de) {

	if (de == 0) {
		ll res = Cb(n, vec, 1);

		for (size_t i = 0; i < 3; i++)
		{
			if (use1[i]) continue;
			use1[i] = true;
			vec[i] = n / xa[i];

			ll val = Ca(n - (vec[i] * xa[i]), vec, 0);
			val = max(val, Cb(n - (vec[i] * xa[i]), vec, 1));
			res = max(res, val);
			vec[i] = 0;
			use1[i] = false;
		}
		return res;
	}
	else if (de == 1) {
		ll res = 0;
		for (int i = 0; i < 3; i++)
		{
			res += vec[i] * xa[i];
		}
		return res;
	}

}
bool use2[3];
ll Cb(ll n, vector<ll> vec, int de) {

	ll res = 0;

	for (size_t i = 0; i < 3; i++)
	{
		if (use2[i]) continue;
		use2[i] = true;
		ll tmp = vec[i];

		vec[i] = n / xb[i];
		ll val = Cb(n - (vec[i] * xb[i]), vec, de);
		val = max(val, Ca(n - (vec[i] * xb[i]), vec, (de == 2 ? 0 : de)));
		ll val2 = tmp * xb[i];
		vec[i] = 0;
		val = max(val, val2 + Cb(n, vec, de));
		res = max(res, val);
		use2[i] = false;
	}
	return res;

}
void solv() {

	ll n, m;
	cin >> n >> m;
	ll s[2010],t[2010];
	for (size_t i = 0; i < n; i++)
	{
		cin >> s[i];
	}

	for (size_t i = 0; i < m; i++)
	{
		cin >> t[i];
	}

	ll dp[2010][2010];
	memset(dp, 0, sizeof(dp));
	for (size_t i = 1; i <= n; i++)
	{
		for (size_t j = 1; j  <= m; j ++)
		{
			if (s[i - 1] == t[j - 1]) {
				dp[i][j] = dp[i][j - 1] + dp[i - 1][j] + 1;
			}
			else {
				dp[i][j] = dp[i - 1][j - 1] + (((dp[i][j - 1] + INF) - dp[i - 1][j - 1]) % INF) + (((dp[i - 1][j] + INF) - dp[i - 1][j - 1]) % INF);
			}
			dp[i][j] %= INF;
		}
	}
	cout << (dp[n][m] + 1) % INF << endl;
}

int main() {
	//	COMinit();
	solv();

	return 0;
}


Measured memory_bytes: 32000