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++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include<iostream>
#include<iomanip>
#include<vector>
#include<string>
#include<math.h>
#include<algorithm>
#include<numeric>
#include<list>
#include<stack>
#include<tuple>
#include<map>
#include<functional>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<LL> VLL;
typedef vector<ULL> VULL;
typedef vector<VLL> VVLL;


class Large_Integer {
private:
	//n進数
	static const LL shinsuu = 7;

	//符号付絶対値で表現
	LL sign;
	VLL numbers;

	//補数表現された整数の足し算
	static VLL plusVector(VLL a, VLL b) {
		VLL ans(max(a.size(), b.size()), 0);

		for (LL i = 0; i < ans.size(); i++) {
			if (i < a.size())ans[i] += a[i];
			if (i < b.size())ans[i] += b[i];

			if (i + 1 < ans.size()) {
				ans[i + 1] += (ans[i] / Large_Integer::shinsuu);
			}

			ans[i] %= Large_Integer::shinsuu;
		}

		return ans;
	}

	//符号付絶対値を補数表現に変換
	static VLL ToVLL(Large_Integer const& a, LL const& min) {
		LL i;
		VLL ans;
		if (a.sign == 1) {
			ans = VLL(max(min, (LL)a.numbers.size()) + 5, 0);
			for (i = 0; i < a.numbers.size(); i++) {
				ans[i] += a.numbers[i];
			}
		}

		else
		{
			ans = VLL(max(min, (LL)a.numbers.size()) + 5, Large_Integer::shinsuu - 1);
			for (i = 0; i < a.numbers.size(); i++) {
				ans[i] -= a.numbers[i];
			}
			ans = Large_Integer::plusVector(ans, VLL(1, 1));
		}

		return ans;
	}

	//補数表現を符号付き絶対値に変換
	static Large_Integer ToInteger(VLL const& a) {
		Large_Integer ans;
		LL i, j, k, n;
		n = a.size();

		if (a[n - 1] == Large_Integer::shinsuu - 1) {
			auto temp = VLL(n, Large_Integer::shinsuu - 1);
			temp = Large_Integer::plusVector(a, temp);
			//ここから

			for (i = 0; i < temp.size(); i++) {
				temp[i] -= Large_Integer::shinsuu;
				temp[i] *= -1;
			}

			ans.sign = -1;
			ans.numbers = temp;
			ans.Syusei();
		}

		else
		{
			ans.sign = 1;
			ans.numbers = a;
			ans.Syusei();
		}

		return ans;
	}


	//シフト演算子
	Large_Integer operator<<(Large_Integer const& a)const {
		LL shift = a.to_LongLong(), i;
		if (shift < 0) {
			return *this >> (shift * -1);
		}

		Large_Integer ans = *this;

		ans.numbers = VLL(this->numbers.size() + shift, 0);

		for (i = 0; i < this->numbers.size(); i++) {
			ans.numbers[i + shift] += this->numbers[i];
		}

		ans.Syusei();

		return ans;
	}

	Large_Integer operator>>(Large_Integer const& a)const {
		LL shift = a.to_LongLong(), i;
		if (shift < 0) {
			return *this << (shift * -1);
		}

		Large_Integer ans = *this;

		ans.numbers = VLL(max((LL)0, (LL)this->numbers.size() - shift), 0);

		for (i = 0; i < this->numbers.size(); i++) {
			if (i - shift >= 0) {
				ans.numbers[i - shift] = this->numbers[i];
			}
		}

		ans.Syusei();

		return ans;
	}


	//掛け算(long long)
	Large_Integer operator*(LL const& b)const {
		Large_Integer ans;

		ans.sign = this->sign;
		ans.numbers = VLL(this->numbers.size() + 1, 0);

		LL i, a = b;

		if (a < 0) {
			a *= -1;
			ans.sign *= -1;
		}

		for (i = 0; i < this->numbers.size(); i++) {
			ans.numbers[i] = a * this->numbers[i];
		}

		for (i = 0; i < ans.numbers.size(); i++) {
			if (i + 1 < ans.numbers.size()) {
				ans.numbers[i + 1] = (ans.numbers[i] / Large_Integer::shinsuu);
			}

			ans.numbers[i] %= Large_Integer::shinsuu;
		}

		return ans;
	}
	
	//誤りの検知と修正
	void Syusei() {
		LL i, j, k;

		if (abs(this->sign) != 1) {
			j = 0;
			j = 1 / j;
		}

		k = 0;

		for (i = 0; i < this->numbers.size(); i++) {
			if (this->numbers[i] < 0) {
				j = 0;
				j = 1 / j;
			}

			if (i + 1 < this->numbers.size()) {
				this->numbers[i + 1] += (this->numbers[i] / Large_Integer::shinsuu);
			}
			this->numbers[i] %= Large_Integer::shinsuu;

			if (this->numbers[i] > 0)k = i + 1;
		}


		VLL ans(k, 0);

		for (i = 0; i < k; i++) {
			ans[i] = this->numbers[i];
		}

		this->numbers = ans;

		if (this->sign == -1 && this->numbers.size() == 0) {
			this->sign = 1;
		}
	}


public:
	//コンストラクタたち
	Large_Integer(Large_Integer const& b) {
		*this = b;
	}

	Large_Integer(LL const& b) {
		if (b < 0)this->sign = -1;
		else this->sign = 1;

		auto c = abs(b);

		while (c > 0)
		{
			this->numbers.push_back(c % this->shinsuu);
			c /= this->shinsuu;
		}

		this->Syusei();
	}

	Large_Integer() {
		this->sign = 1;
		this->numbers = VLL(0);
	}

	//long long型に変換する
	LL to_LongLong()const {
		LL ans = 0, i;

		for (i = this->numbers.size() - 1; i >= 0; i--) {
			ans *= this->shinsuu;
			ans += this->numbers[i];
		}

		ans *= this->sign;

		return ans;
	}

	//代入演算子
	Large_Integer operator=(Large_Integer const& b) {
		this->sign = b.sign;
		this->numbers = b.numbers;

		return *this;
	}


	//足し算
	Large_Integer operator+(Large_Integer const& b)const {
		LL i, j;

		VLL x, y;
		LL size = max(this->numbers.size(), b.numbers.size());

		x = Large_Integer::ToVLL(*this, size);
		y = Large_Integer::ToVLL(b, size);

		x = Large_Integer::plusVector(x, y);
		
		auto ans = Large_Integer::ToInteger(x);
		ans.Syusei();

		return ans;
	}

	Large_Integer operator+=(Large_Integer const& b) {
		return *this = *this + b;
	}

	Large_Integer operator*(Large_Integer const& b)const {
		Large_Integer ans;
		//ここから
	}

	//未完成
	bool operator<(Large_Integer const& b) {
		LL i, j, k;

		if (this->sign < b.sign) {
			return true;
		}
		if (this->sign > b.sign) {
			return false;
		}

		if (this->sign == 1) {
			if (this->numbers.size() < b.numbers.size()) {
				return true;
			}
			if (this->numbers.size() > b.numbers.size()) {
				return false;
			}

			for (i = this->numbers.size() - 1; i >= 0; i--) {
				if (this->numbers[i] < b.numbers[i]) {
					return true;
				}
				if (this->numbers[i] > b.numbers[i]) {
					return false;
				}
			}
		}
	}

};

//関数詰め合わせ
class MYCP {
public:

	static const LL MOD_CONST = (LL)1000 * 1000 * 1000 + 7;

	static LL DebugFlag;

	//数値を区切って文字列にする
	static string MakeString_LongLong(vector<long long> const& numbers, string const& str) {
		if (numbers.size() == 0)return "";
		string result = "" + to_string(numbers[0]);
		for (long long i = 1; i < numbers.size(); i++) {
			result += str;
			result += to_string(numbers[i]);
		}

		return result;
	}

	//空白で区切る為のオーバーロード
	static string MakeString_LongLong(vector<long long> const& numbers) {
		if (numbers.size() == 0)return "";
		string result = "" + to_string(numbers[0]);
		for (long long i = 1; i < numbers.size(); i++) {
			result += " ";
			result += to_string(numbers[i]);
		}

		return result;
	}



	//文字列の配列を改行を挟んでまとめる
	static string MakeString_VectorString(vector<string> const& str) {
		string result = "";
		for (long long i = 0; i < str.size(); i++) {
			result += str[i] + "\n";
		}

		return result;
	}

	//文字列を必要な個数だけ読み取る
	static vector<string> MyReadLineSplit(LL n) {
		vector<string> str(n);
		for (long long i = 0; i < n; i++) {
			std::cin >> str[i];
		}

		return str;
	}

	//数値を必要な個数だけ読み取る
	static vector<long long> ReadInts(long long number) {
		vector<long long> a(number);
		for (int i = 0; i < number; i++) {
			std::cin >> a[i];
		}

		return a;
	}

	//渡された自然数が素数ならtureを返す
	static bool PrimeCheck_Int(long long number) {
		if (number < 2)return false;

		for (ULL i = 2; i*i <= number; i++) {
			if (number%i == 0)return false;
		}

		return true;
	}

	//渡された数値以下の素数表を作る
	static vector<long long> MakePrimeList(long long n) {
		vector<long long> list;
		LL i, j, p;
		bool flag;
		for (i = 2; i <= n; i++) {
			flag = true;
			for (j = 0; j < list.size(); j++) {

				if (!(list[j] * list[j] <= i))break;

				if (i%list[j] == 0) {
					flag = false;
					break;
				}
			}
			if (flag)list.push_back(i);
		}

		return list;
	}



	//文字列の分割
	static vector<string> split(string const& str, char sep)
	{
		vector<std::string> v;        // 分割結果を格納するベクター
		auto first = str.begin();              // テキストの最初を指すイテレータ
		while (first != str.end()) {         // テキストが残っている間ループ
			auto last = first;                      // 分割文字列末尾へのイテレータ
			while (last != str.end() && *last != sep)       // 末尾 or セパレータ文字まで進める
				last++;
			v.push_back(string(first, last));       // 分割文字を出力
			if (last != str.end())
				last++;
			first = last;          // 次の処理のためにイテレータを設定
		}
		return v;
	}

	//合計を求める
	template<typename T>
	static LL Sum(T const& a) {
		LL sum = 0;
		auto itr = a.begin();

		while (itr != a.end())
		{
			sum += (*itr);
			itr++;
		}

		return sum;
	}

	//小文字ならtrueを返す
	static bool Komoji(char a) {
		if (a >= 'a'&&a <= 'z')return true;

		return false;
	}

	//大文字ならtrueを返す
	static bool Oomoji(char a) {
		if (a >= 'A'&&a <= 'Z')return true;

		return false;
	}

	//切り上げの整数値割り算
	static LL KiriageWarizan(LL a, LL b) {
		LL result = a / b;

		if (a%b > 0)result++;

		return result;
	}

	//最大公約数を求める
	static LL GreatestCommonFactor(LL a, LL b) {
		a = abs(a);
		b = abs(b);

		LL temp;
		if (a < b) {
			temp = b;
			b = a;
			a = temp;
		}

		while (b > 0)
		{
			temp = a % b;
			a = b;
			b = temp;
		}

		return a;
	}

	//最小公倍数を求める
	static LL LeastCommonMultiple(LL a, LL b) {
		return (a / GreatestCommonFactor(a, b))*b;
	}

	//二次元配列を行列とみなして転置する
	static VVLL VVLLturn(VVLL a) {

		if (a.size() == 0)return VVLL(0);

		VVLL result(a[0].size(), VLL(a.size()));
		LL i, j;
		for (i = 0; i < a.size(); i++) {
			for (j = 0; j < a[0].size(); j++) {
				result[j][i] = a[i][j];
			}
		}

		return result;
	}

	//素因数分解、素数、指数の順
	static vector<VLL> PrimeFactorization(LL n) {
		VLL p_list, s_list;

		LL i, j, k, count;

		for (i = 2; n > 1; i++) {
			if (i*i > n) {
				p_list.push_back(n);
				s_list.push_back(1);
				break;
			}

			if (n%i == 0) {
				count = 0;
				while (n%i == 0)
				{
					n /= i;
					count++;
				}

				p_list.push_back(i);
				s_list.push_back(count);
			}
		}

		vector<VLL> result;
		result.push_back(p_list);
		result.push_back(s_list);

		return MYCP::VVLLturn(result);
	}

	//整数nの約数の配列を作る
	static VLL MakeYakusuList(LL n) {
		auto primes = MYCP::PrimeFactorization(n);
		VLL ans;
		VLL roop(primes.size(), 0);

		LL i, j, k, m, size = roop.size();

		while (true)
		{
			LL a = 1;

			for (i = 0; i < size; i++) {
				for (j = 0; j < roop[i]; j++) {
					a *= primes[i][0];
				}
			}

			ans.push_back(a);

			roop[0]++;

			for (i = 0; i < size; i++) {
				if (i + 1 < size) {
					roop[i + 1] += (roop[i] / (primes[i][1] + 1));
				}
				roop[i] %= (primes[i][1] + 1);
			}

			bool flag = true;
			for (i = 0; i < size; i++) {
				if (roop[i] != 0)flag = false;
			}

			if (flag)break;
		}

		return MYCP::Sort(ans);
	}

	//組み合わせ nCr
	static LL Combination(LL n, LL r) {
		r = min(r, n - r);

		VLL p(n + 1, 0);

		LL i, j, k, a, b, c;

		for (i = 1; i <= r; i++) {
			auto temp = MYCP::PrimeFactorization(i);
			temp = MYCP::VVLLturn(temp);
			if (temp.size() == 0) {
				temp = VVLL(2, VLL(0));
			}

			for (j = 0; j < temp[0].size(); j++) {
				p[temp[0][j]] -= temp[1][j];
			}

			a = i + n - r;
			temp = MYCP::PrimeFactorization(a);
			temp = MYCP::VVLLturn(temp);
			if (temp.size() == 0) {
				temp = VVLL(2, VLL(0));
			}

			for (j = 0; j < temp[0].size(); j++) {
				p[temp[0][j]] += temp[1][j];
			}

		}

		LL result = 1;

		for (i = 0; i < p.size(); i++) {
			if (p[i] > 0) {

				for (j = 0; j < p[i]; j++) {
					result *= i;
					result %= MYCP::MOD_CONST;
				}

			}
		}

		return result;
	}

	//符号
	static  LL sign(LL const x) {
		if (x > 0)return 1;
		if (x < 0)return -1;
		return 0;
	}

	//円周率
	static double PI() {
		return (double)3.1415926535898;
	}

	//指定した桁でdoubleを出す。改行はしない。
	static void CoutDoubleKeta(double a, LL keta) {
		cout << setprecision(keta) << a << flush;
	}

	//コンテナクラスの出力
	template<typename T>
	static T CoutVector(T const& ls) {
		LL i, j, k, size = distance(ls.begin(), ls.end());

		auto itr = ls.begin();

		for (i = 0; i < size - 1; i++) {
			cout << *itr << " " << flush;
			itr++;
		}

		cout << *itr << flush;

		return ls;
	}

	//コンテナクラスをソートする
	template<typename T>
	static T Sort(T & ls) {
		sort(ls.begin(), ls.end());

		return ls;
	}

	//順序関数付きでコンテナクラスをソートする
	template<typename T, typename F>
	static T Sort(T & ls, F func) {
		sort(ls.begin(), ls.end(), func);

		return ls;
	}

	//コンテナクラスを逆順に並び替える
	template<typename T>
	static T Reverse(T & ls) {
		reverse(ls.begin(), ls.end());

		return ls;
	}

	//コンテナクラスの条件を満たす要素を数え上げる。bool func(S x)
	template<typename T, typename S>
	static LL Count(T const& ls, S func) {
		LL ans = 0;
		auto itr = ls.begin();
		while (itr != ls.end()) {
			if (func(*itr))ans++;
			itr++;
		}
		return ans;
	}

	//コンテナクラスの要素をすべて更新する。S func(S x)
	template<typename T, typename S>
	static T AllUpdate(T & ls, S func) {
		auto itr = ls.begin();
		while (itr != ls.end()) {
			*itr = func(*itr);
			itr++;
		}
		return ls;
	}

	//リストをベクターに変換する
	template<typename T>
	static vector<T> FromListToVector(list<T> a) {
		vector<T> ans;
		for (auto itr = a.begin(); itr != a.end(); itr++) {
			ans.push_back(*itr);
		}

		return ans;
	}

	//ベクターをリストに変換する
	template<typename T>
	static list<T> FromVectorToList(vector<T> a) {
		list<T> ans;
		for (auto itr = a.begin(); itr != a.end(); itr++) {
			ans.push_back(*itr);
		}

		return ans;
	}

	//デバッグ用出力
	template<typename T>
	static LL DebugPrintf(T output) {

		if (MYCP::DebugFlag) {
			std::cout << output << endl;
		}

		return MYCP::DebugFlag;
	}

	//デバッグ用入力
	static  LL DebugCin() {
		LL a;

		if (MYCP::DebugFlag) {
			cin >> a;
		}

		return a;
	}
};
LL MYCP::DebugFlag = 0;

//累積和を求めるクラス
class Ruisekiwa {
private:
	vector<LL> list;

public:

	void MakeArray(vector<LL> data) {
		LL i;
		list = data;
		list.push_back(0);
		list[0] = 0;
		for (i = 1; i < list.size(); i++) {
			list[i] = list[i - 1] + data[i - 1];
		}

	}

	LL Sum(LL start, LL end) {
		if (end < start) {
			std::cout << "startがendより大きいです";
			return 0;
		}
		if (start < 0 || end >= list.size()) {
			std::cout << "範囲が異常";
			return 0;
		}

		return list[end] - list[start];
	}

};

//n進数を管理するクラス
class N_Number {
public:
	N_Number(LL n, LL keta) {
		this->N_Shinsuu = n;

		VLL temp(keta, 0);
		this->numbers = temp;

	}

	//数を足す
	void plus(LL a) {
		if (a < 0) {
			a *= (-1);
			this->minus(a);
			return;
		}

		this->numbers[0] += a;
		LL size = this->numbers.size();
		for (LL i = 0; i < size; i++) {
			if (i + 1 < size) {
				this->numbers[i + 1] += this->numbers[i] / this->N_Shinsuu;
			}
			this->numbers[i] %= this->N_Shinsuu;
		}
	}

	//全ての桁が同じ数字になっていればその数字を返す。それ以外の場合は -1 を返す
	LL check() {
		LL a = this->numbers[0];

		for (LL i = 0; i < this->numbers.size(); i++) {
			if (this->numbers[i] != a)return -1;
		}

		return a;
	}

	LL getNumber(LL keta) {
		return this->numbers[keta];
	}

	LL getKeta() {
		return this->numbers.size();
	}

	LL getShinsuu() {
		return this->N_Shinsuu;
	}

	void setNumber(LL keta, LL number) {
		if (0 <= number && number < this->getShinsuu()) {
			if (0 <= keta && keta < this->getKeta()) {
				this->numbers[keta] = number;
				return;
			}
		}

		cout << "er" << endl;
	}

	void setAllNumbers(LL number) {
		LL size = this->getKeta(), i;
		for (i = 0; i < size; i++) {
			this->setNumber(i, number);
		}
	}

	string to_string_KetaSoroe() {
		string s = "";
		for (LL i = this->getKeta() - 1; i >= 0; i--) {
			s += to_string(this->getNumber(i));
		}

		return s;
	}

private:
	void minus(LL a) {
		LL i, j, k, zettaiti = abs(a);

		k = MYCP::KiriageWarizan(zettaiti, this->N_Shinsuu);
		j = k * (this->N_Shinsuu - 1);

		for (i = 0; i < this->getKeta(); i++) {
			this->numbers[i] += j;
		}

		this->numbers[0] += k - a;
		this->plus(0);
	}

	VLL numbers;
	LL N_Shinsuu;
};

//UnionFind
class Union_Find {
private:
	VLL tree;
	VLL count;

	LL root(LL a) {
		if (this->tree[a] == a)return a;
		return this->tree[a] = this->root(this->tree[a]);
	}

public:
	Union_Find(LL n) {
		VLL set(n);
		this->tree = set;
		this->count = set;

		for (LL i = 0; i < n; i++) {
			this->tree[i] = i;
			this->count[i] = 1;
		}
	}

	void unite(LL a, LL b) {
		LL x, y;

		if (!this->Check(a, b)) {
			x = this->getCount(a) + getCount(b);

			y = this->root(a);
			this->count[y] = x;

			y = this->root(b);
			this->count[y] = x;
		}


		x = this->root(a);
		y = this->root(b);

		this->tree[x] = y;

	}

	bool Check(LL a, LL b) {
		return this->root(a) == this->root(b);
	}

	LL getCount(LL index) {
		LL temp = this->root(index);
		return this->count[temp];
	}

	VLL getList() {
		VLL ans(this->tree.size(), 0);
		for (LL i = 0; i < ans.size(); i++) {
			ans[i] = this->root(i);
		}

		return ans;
	}

};

//プラスマイナス無限に対応したlong long型
class INF_LONG_LONG {
private:
	LL inf, n;

public:

	//コンストラクタ
	INF_LONG_LONG(LL a) {
		this->n = a;
		this->inf = 0;

		this->Syusei();
	}

	INF_LONG_LONG() {
		*this = INF_LONG_LONG(0);
	}

	INF_LONG_LONG(INF_LONG_LONG const& a) {
		this->n = a.n;
		this->inf = a.inf;

		this->Syusei();
	}

	//ゲッター
	LL getN()const {
		return this->n;
	}

	LL getInf()const {
		return this->inf;
	}

	//正の無限大生成
	static INF_LONG_LONG plus_inf() {
		INF_LONG_LONG a;
		a.n = 0;
		a.inf = 1;

		a.Syusei();

		return a;
	}

	//負の無限大生成
	static INF_LONG_LONG minus_inf() {
		INF_LONG_LONG a;
		a.n = 0;
		a.inf = -1;

		a.Syusei();

		return a;
	}

	//符号を取得
	LL sign() const {
		if (this->inf != 0) {
			return this->inf;
		}

		return MYCP::sign(this->n);
	}

	//代入演算子
	INF_LONG_LONG operator=(INF_LONG_LONG const& b) {
		this->n = b.n;
		this->inf = b.inf;

		this->Syusei();

		return *this;
	}

	INF_LONG_LONG operator=(LL const& b) {
		*this = INF_LONG_LONG(b);

		this->Syusei();

		return *this;
	}

	//比較演算子
	bool operator==(INF_LONG_LONG const& b) const {
		if (this->n == b.n&&this->inf == b.inf)return true;

		return false;
	}

	bool operator!=(INF_LONG_LONG const& b)const {
		return !(*this == b);
	}

	bool operator<(INF_LONG_LONG const& b) const {
		if (this->inf < b.inf)return true;

		if (this->inf > b.inf)return false;

		return this->n < b.n;
	}

	bool operator>(INF_LONG_LONG const& b) const {
		return b < *this;
	}

	bool operator<=(INF_LONG_LONG const& b) const {
		return !(*this > b);
	}

	bool operator>=(INF_LONG_LONG const& b) const {
		return !(*this < b);
	}

	//算術演算子
	INF_LONG_LONG operator+(INF_LONG_LONG const& b) const {
		if (max(this->inf, b.inf) > 0)return INF_LONG_LONG::plus_inf();
		if (min(this->inf, b.inf) < 0)return INF_LONG_LONG::minus_inf();

		auto ans = *this;
		ans.n += b.n;

		ans.Syusei();

		return ans;
	}

	INF_LONG_LONG operator*(INF_LONG_LONG const& b) const {

		if (*this == INF_LONG_LONG(0) || b == INF_LONG_LONG(0)) {
			return INF_LONG_LONG(0);
		}

		if (this->inf != 0 || b.inf != 0) {
			LL s = this->sign() * b.sign();

			INF_LONG_LONG ans(0);
			ans.n = 0;
			ans.inf = s;

			ans.Syusei();

			return ans;
		}

		INF_LONG_LONG ans(0);

		ans.n = this->n * b.n;

		ans.Syusei();

		return ans;
	}

	INF_LONG_LONG operator-(INF_LONG_LONG const& b) const {
		auto ans = (*this + (INF_LONG_LONG(-1) * b));
		ans.Syusei();

		return ans;
	}

	INF_LONG_LONG operator/(INF_LONG_LONG const& b)const {
		if (b == INF_LONG_LONG(0)) {
			LL a = this->n / b.n;

			return INF_LONG_LONG(a);
		}

		if (b.inf != 0) {
			return INF_LONG_LONG(0);
		}

		if (*this == INF_LONG_LONG(0)) {
			return INF_LONG_LONG(0);
		}

		if (this->inf != 0) {
			LL s = this->sign() * b.sign();

			return INF_LONG_LONG::plus_inf() * INF_LONG_LONG(s);
		}

		INF_LONG_LONG ans;

		ans.n = this->n / b.n;

		ans.Syusei();

		return ans;
	}

	INF_LONG_LONG operator%(INF_LONG_LONG const& b)const {
		if (this->inf == 0 && b.inf == 0) {
			INF_LONG_LONG ans;

			ans.n = this->n % b.n;

			ans.Syusei();

			return ans;
		}

		auto x = *this / b;
		x.Syusei();
		auto ans = *this - b * x;
		ans.Syusei();

		return ans;
	}

	//複合代入演算子
	INF_LONG_LONG operator+=(INF_LONG_LONG const& b) {
		auto ans = *this + b;
		*this = ans;

		return *this;
	}

	INF_LONG_LONG operator-=(INF_LONG_LONG const& b) {
		auto ans = *this - b;
		*this = ans;

		return *this;
	}

	INF_LONG_LONG operator*=(INF_LONG_LONG const& b) {
		auto ans = *this * b;
		*this = ans;

		return *this;
	}

	INF_LONG_LONG operator/=(INF_LONG_LONG const& b) {
		auto ans = *this / b;
		*this = ans;

		return *this;
	}

	INF_LONG_LONG operator%=(INF_LONG_LONG const& b) {
		auto ans = *this % b;
		*this = ans;

		return *this;
	}

	//符号演算子
	INF_LONG_LONG operator+()const {
		return *this;
	}

	INF_LONG_LONG operator-()const {
		return *this * INF_LONG_LONG(-1);
	}

	//前置きインクリメント・デクリメント
	INF_LONG_LONG operator++() {
		this->n++;
		this->Syusei();

		return *this;
	}

	INF_LONG_LONG operator--() {
		this->n--;
		this->Syusei();

		return *this;
	}

	//後置きインクリメント・デクリメント
	INF_LONG_LONG operator++(int) {
		auto copy = *this;
		++(*this);
		return copy;
	}

	INF_LONG_LONG operator--(int) {
		auto copy = *this;
		--(*this);
		return copy;
	}

	//文字列への変換
	string ToString()const {
		if (this->inf == 1) {
			return "+INF";
		}

		if (this->inf == -1) {
			return "-INF";
		}

		return to_string(this->n);
	}

private:
	void Syusei() {
		if (this->inf != 0) {
			this->n = 0;
		}
	}
};
typedef INF_LONG_LONG ILL_TYPE;
typedef vector<ILL_TYPE> VILL_TYPE;
typedef vector<VILL_TYPE> VVILL_TYPE;

//ワーシャルフロイド
class WarshallFloyd {
public:

	//最短距離を記録
	VVILL_TYPE d;

	//頂点数
	LL v;

	//vは頂点数、edge_cost_listは辺の情報{始点、終点、コスト}の配列。無向グラフの場合、逆矢印の辺に注意。
	WarshallFloyd(LL v, VVLL edge_cost_list) {
		this->v = v;

		this->d = VVILL_TYPE(v, VILL_TYPE(v, ILL_TYPE::plus_inf()));

		LL i, j, k, a, b, c;

		for (i = 0; i < edge_cost_list.size(); i++) {
			a = edge_cost_list[i][0];
			b = edge_cost_list[i][1];
			c = edge_cost_list[i][2];

			this->d[a][b] = ILL_TYPE(c);
		}

		for (i = 0; i < v; i++) {
			this->d[i][i] = ILL_TYPE(0);
		}


		//ここから計算
		for (k = 0; k < v; k++) {
			for (i = 0; i < v; i++) {
				for (j = 0; j < v; j++) {
					d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
				}
			}
		}


	}
};

//ベルマンフォード
class BellmanFord {
public:
	//辺のリスト
	VVILL_TYPE edge;

	//頂点数、辺数
	LL v, e;

	//始点
	LL s;

	//最短距離
	VILL_TYPE d;

	//vは頂点数、startは始点、edge_cost_listは辺の情報{始点、終点、コスト}の配列。
	BellmanFord(LL v, LL start, VVLL edge_cost_list) {
		this->v = v;
		this->s = start;
		this->e = edge_cost_list.size();
		this->d = VILL_TYPE(v, ILL_TYPE::plus_inf());
		this->d[start] = 0;

		LL i, j, k;
		for (i = 0; i < this->e; i++) {
			VILL_TYPE temp;
			LL a, b, c;
			a = edge_cost_list[i][0];
			b = edge_cost_list[i][1];
			c = edge_cost_list[i][2];

			temp.push_back(ILL_TYPE(a));
			temp.push_back(ILL_TYPE(b));
			temp.push_back(ILL_TYPE(c));

			this->edge.push_back(temp);
		}


		this->DoUpdata();

		auto cpy = this->d;

		this->DoUpdata();

		for (i = 0; i < this->d.size(); i++) {
			if (this->d[i] != cpy[i]) {
				this->d[i] = ILL_TYPE::minus_inf();
			}
		}

		this->DoUpdata();
	}

private:
	void DoUpdata() {
		LL i, j, k;
		for (i = 0; i <= this->v; i++) {
			bool update = true;

			for (j = 0; j < this->e; j++) {
				ILL_TYPE c;
				LL a, b;
				a = this->edge[j][0].getN();
				b = this->edge[j][1].getN();
				c = this->edge[j][2];

				if (this->d[a] < ILL_TYPE::plus_inf()) {
					if (this->d[a] + c < this->d[b]) {
						update = false;

						this->d[b] = this->d[a] + c;
					}
				}
			}

			if (update)break;
		}
	}
};

//ダイクストラ
class Dijkstra {
public:
	Dijkstra(LL v, LL start, VVLL edge_cost_list) {

	}
};

//ライブラリはここまで

//ここから下を書く

//ここからメイン

int main(void) {
	MYCP::DebugFlag = 0;

	LL i, j, k, n, m;
	cin >> n >> m;

	auto s = MYCP::ReadInts(n);
	auto t = MYCP::ReadInts(m);

	if (n < m) {
		swap(s, t);
		swap(n, m);
	}

	if (true) {
		VLL temp = VLL(n, -1);

		for (i = 0; i < m; i++) {
			temp[i] = t[i];
		}

		t = temp;
	}

	m = n;

	VLL dp(n, 0);

	if (s[0] == t[0])dp[0] = 1;

	for (i = 1; i < n; i++) {
		dp[i] = dp[i - 1];
		if (s[i] == t[i])dp[i] *= 2;


	}

	return 0;
}