#include <bits/stdc++.h>
using namespace std;
inline int toint(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class t>
inline string tostring(t x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
using ll = long long;
using ull = unsigned long long;
inline ll floor(ll a, ull b) {
  ll llb = b;
  if (a >= 0) {
    return a / llb;
  } else {
    return -((-a + llb - 1) / llb);
  }
}
inline ll ceil(ll a, ull b) {
  ll llb = b;
  if (a >= 0) {
    return (a + llb - 1) / llb;
  } else {
    return -(-a / llb);
  }
}
inline bool isPower2(ull a) {
  if (a == 0) {
    return false;
  }
  return !(a & (a - 1));
}
inline ll getMaxEffectiveBit(ull a) {
  ll index = -1;
  for (; a != 0; a >>= 1) {
    ++index;
  }
  return index;
}
inline ll getSpecifiedBit(ull a, unsigned bit) {
  return (a & (1LL << bit)) >> bit;
}
inline ull getGcd(ull a, ull b) {
  if (b == 0) {
    return a;
  }
  return getGcd(b, a % b);
}
template <class Integer>
inline Integer getPower(Integer base, ull exponential) {
  Integer result = 1;
  while (exponential >= 1) {
    if (exponential & 1) {
      result = result * base;
    }
    base = base * base;
    exponential >>= 1;
  }
  return result;
}
template <class Integer>
class ResidueInteger {
 private:
  Integer mod_;
  Integer n_;
  static Integer global_mod_;
  static inline pair<Integer, Integer> getBezoutsIdentitySolution(Integer a,
                                                                  Integer b) {
    if (b == 0) {
      return {1, 0};
    }
    auto sol = getBezoutsIdentitySolution(b, a % b);
    return {sol.second, sol.first - (a / b) * sol.second};
  }

 public:
  Integer getModValue(const Integer& n) const {
    return (n % mod_ + mod_) % mod_;
  }
  inline Integer getModInverse(const Integer& n) const {
    auto sol = getBezoutsIdentitySolution(n, mod_);
    if (n * sol.first + mod_ * sol.second != 1) {
      return -1;
    }
    return getModValue(sol.first);
  }
  ResidueInteger() : mod_(global_mod_), n_(getModValue(0)) {}
  ResidueInteger(Integer n) : mod_(global_mod_), n_(getModValue(n)) {}
  ResidueInteger(Integer n, Integer mod) : mod_(mod), n_(getModValue(n)) {}
  inline ResidueInteger operator+(const ResidueInteger& rhs) const {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    return {this->n_ + rhs.n_, this->mod_};
  }
  inline ResidueInteger operator+(const Integer& rhs) const {
    return {this->n_ + getModValue(rhs), this->mod_};
  }
  friend inline ResidueInteger operator+(const Integer& lhs,
                                         const ResidueInteger& rhs) {
    return {rhs.getModValue(lhs) + rhs.n_, rhs.mod_};
  }
  inline ResidueInteger& operator+=(const ResidueInteger& rhs) {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    this->n_ = getModValue(this->n_ + rhs.n_);
    return *this;
  }
  inline ResidueInteger& operator+=(const Integer& rhs) {
    this->n_ = getModValue(this->n_ + getModValue(rhs));
    return *this;
  }
  inline ResidueInteger operator-(const ResidueInteger& rhs) const {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    return {this->n_ - rhs.n_, this->mod_};
  }
  inline ResidueInteger operator-(const Integer& rhs) const {
    return {this->n_ - getModValue(rhs), this->mod_};
  }
  friend inline ResidueInteger operator-(const Integer& lhs,
                                         const ResidueInteger& rhs) {
    return {rhs.getModValue(lhs) - rhs.n_, rhs.mod_};
  }
  inline ResidueInteger& operator-=(const ResidueInteger& rhs) {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    this->n_ = getModValue(this->n_ - rhs.n_);
    return *this;
  }
  inline ResidueInteger& operator-=(const Integer& rhs) {
    this->n_ = getModValue(this->n_ - getModValue(rhs));
    return *this;
  }
  inline ResidueInteger operator*(const ResidueInteger& rhs) const {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    return {this->n_ * rhs.n_, this->mod_};
  }
  inline ResidueInteger operator*(const Integer& rhs) const {
    return {this->n_ * getModValue(rhs), this->mod_};
  }
  friend inline ResidueInteger operator*(const Integer& lhs,
                                         const ResidueInteger& rhs) {
    return {rhs.getModValue(lhs) * rhs.n_, rhs.mod_};
  }
  inline ResidueInteger& operator*=(const ResidueInteger& rhs) {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    this->n_ = getModValue(this->n_ * rhs.n_);
    return *this;
  }
  inline ResidueInteger& operator*=(const Integer& rhs) {
    this->n_ = getModValue(this->n_ * getModValue(rhs));
    return *this;
  }
  inline ResidueInteger operator/(const ResidueInteger& rhs) const {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    return {this->n_ * getModInverse(rhs.n_), this->mod_};
  }
  inline ResidueInteger operator/(const Integer& rhs) const {
    return {this->n_ * getModInverse(getModValue(rhs)), this->mod_};
  }
  friend inline ResidueInteger operator/(const Integer& lhs,
                                         const ResidueInteger& rhs) {
    return {rhs.getModValue(lhs) * rhs.getModInverse(rhs.n_), rhs.mod_};
  }
  inline ResidueInteger& operator/=(const ResidueInteger& rhs) {
    if (this->mod_ != rhs.mod_) {
      throw invalid_argument("The mods of both operands should be equal.");
    }
    this->n_ = getModValue(this->n_ * getModInverse(rhs.n_));
    return *this;
  }
  inline ResidueInteger& operator/=(const Integer& rhs) {
    this->n_ = getModValue(this->n_ * getModInverse(getModValue(rhs)));
    return *this;
  }
  inline bool operator==(const ResidueInteger& rhs) const {
    return (this->n_ == rhs.n_) && (this->mod_ == rhs.mod_);
  }
  inline bool operator==(const Integer& rhs) const {
    return this->n_ == getModValue(rhs);
  }
  friend bool operator==(const Integer& lhs, const ResidueInteger& rhs) {
    return rhs.getModValue(lhs) == rhs.n_;
  }
  Integer getN() const { return n_; }
  friend std::ostream& operator<<(std::ostream& lhs,
                                  const ResidueInteger& rhs) {
    return lhs << rhs.n_;
  }
  friend std::istream& operator>>(std::istream& lhs, ResidueInteger& rhs) {
    lhs >> rhs.n_;
    return lhs;
  }
};
using rll = ResidueInteger<ll>;
ll mod = 1000000007ll;
template <>
ll rll::global_mod_ = mod;
template <class Integer>
class ResidueCombinatorialCalculator {
 private:
  Integer mod_;
  Integer n_;
  map<Integer, ResidueInteger<Integer>> values_;

 public:
  ResidueCombinatorialCalculator(Integer n, Integer mod) : mod_(mod), n_(n) {
    values_[0] = ResidueInteger<Integer>(1, mod_);
  }
  ResidueInteger<Integer> calculate(Integer r) {
    if (r < 0 || n_ < r) {
      return 0;
    }
    if (values_.count(r) >= 1) {
      return values_[r];
    }
    if (values_.count(n_ - r) >= 1) {
      values_[r] = values_[n_ - r];
      return values_[r];
    }
    if (n_ < r * 2) {
      values_[r] = calculate(n_ - r);
      return values_[r];
    }
    values_[r] = calculate(r - 1) * (n_ - r + 1) / r;
    return values_[r];
  }
};
using rccll = ResidueCombinatorialCalculator<ll>;
ll getValue(ll currN, ll currM, const vector<ll>& Ss, const vector<ll>& Ts,
            const map<ll, vector<ll>>& SValueToPosition,
            map<ll, vector<ll>>& TValueToPosition, vector<vector<ll>>& res) {
  if (res[currN][currM] != -1) {
    return res[currN][currM];
  }
  rll currRes = 0;
  currRes += getValue(currN - 1, currM, Ss, Ts, SValueToPosition,
                      TValueToPosition, res);
  if (TValueToPosition.count(Ss[currN]) > 0) {
    auto valuePositions = TValueToPosition.at(Ss[currN]);
    auto endIter =
        upper_bound(valuePositions.begin(), valuePositions.end(), currM);
    for (auto iter = valuePositions.begin(); iter < endIter; ++iter) {
      currRes += getValue(currN - 1, (*iter) - 1, Ss, Ts, SValueToPosition,
                          TValueToPosition, res);
    }
  }
  res[currN][currM] = currRes.getN();
  return res[currN][currM];
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll N, M;
  cin >> N >> M;
  vector<ll> Ss(N + 1), Ts(M + 1);
  map<ll, vector<ll>> SValueToPosition, TValueToPosition;
  for (ll i = 1; i <= N; ++i) {
    cin >> Ss[i];
    SValueToPosition[Ss[i]].emplace_back(i);
  }
  for (ll i = 1; i <= M; ++i) {
    cin >> Ts[i];
    TValueToPosition[Ts[i]].emplace_back(i);
  }
  vector<vector<ll>> res(N + 1, vector<ll>(M + 1, -1));
  for (ll i = 0; i < N + 1; ++i) {
    res[i][0] = 1;
  }
  for (ll i = 0; i < M + 1; ++i) {
    res[0][i] = 1;
  }
  cout << getValue(N, M, Ss, Ts, SValueToPosition, TValueToPosition, res)
       << endl;
  return 0;
}
