#include <bits/stdc++.h>
using namespace std;
using lli = long long;
using ld = long double;
mt19937 rnd(time(nullptr));
const lli p = 31, mod = 1e9 + 7;
vector<lli> base;
vector<lli> prefix;
lli Mod(lli a, lli b) { return (a % b + b) % b; }
lli Add(lli a, lli b) { return Mod(a + b, mod); }
lli Sub(lli a, lli b) { return Mod(a - b, mod); }
lli Mul(lli a, lli b) { return Mod(a * b, mod); }
void FillBase(lli sz) {
  base.resize(sz);
  base[0] = 1;
  for (lli i = 1; i < sz; i++) base[i] = Mul(base[i - 1], p);
  reverse(base.begin(), base.end());
  prefix.resize(sz);
  prefix[0] = base[0];
  for (lli i = 1; i < sz; i++) prefix[i] = Add(prefix[i - 1], base[i]);
}
lli Query(lli l, lli r) {
  if (l == 0) return prefix[r];
  return Sub(prefix[r], prefix[l - 1]);
}
struct Segtree {
  const lli Neutral = 0, None = -1;
  vector<lli> tree, tadd;
  Segtree(lli sz) : tree(4 * sz), tadd(4 * sz, None) {}
  void build(string& buffer, lli v, lli tl, lli tr);
  lli query(lli left, lli right, lli v, lli tl, lli tr);
  void update(lli left, lli right, lli value, lli v, lli tl, lli tr);
  void push(lli v, lli tl, lli tr);
};
void Segtree::build(string& buffer, lli v, lli tl, lli tr) {
  if (tl == tr) {
    tree[v] = Mul(base[tl], (buffer[tl] - '0' + 3));
    return;
  }
  lli tm = (tl + tr) / 2;
  build(buffer, 2 * v + 1, tl, tm);
  build(buffer, 2 * v + 2, tm + 1, tr);
  tree[v] = Add(tree[2 * v + 1], tree[2 * v + 2]);
}
lli Segtree::query(lli left, lli right, lli v, lli tl, lli tr) {
  push(v, tl, tr);
  if (tr < left || tl > right) return Neutral;
  if (tl >= left && tr <= right) return tree[v];
  lli tm = (tl + tr) / 2;
  auto q1 = query(left, right, 2 * v + 1, tl, tm),
       q2 = query(left, right, 2 * v + 2, tm + 1, tr);
  return Add(q1, q2);
}
void Segtree::update(lli left, lli right, lli value, lli v, lli tl, lli tr) {
  push(v, tl, tr);
  if (tr < left || tl > right) return;
  if (tl >= left && tr <= right) {
    tadd[v] = value;
    push(v, tl, tr);
    return;
  }
  lli tm = (tl + tr) / 2;
  update(left, right, value, 2 * v + 1, tl, tm),
      update(left, right, value, 2 * v + 2, tm + 1, tr);
  tree[v] = Add(tree[2 * v + 1], tree[2 * v + 2]);
}
void Segtree::push(lli v, lli tl, lli tr) {
  if (tadd[v] == None) return;
  tree[v] = Mul(tadd[v] + 3, Query(tl, tr));
  if (tl != tr) {
    tadd[2 * v + 1] = tadd[v];
    tadd[2 * v + 2] = tadd[v];
  }
  tadd[v] = None;
}
inline void Solve() {
  FillBase(1e6);
  lli n = 0, m = 0, k = 0;
  cin >> n >> m >> k;
  string data;
  cin >> data;
  Segtree from(n);
  from.build(data, 0, 0, n - 1);
  for (lli i = 0; i < m + k; i++) {
    lli cmd = 0, l = 0, r = 0, value = 0;
    cin >> cmd >> l >> r >> value;
    l--, r--;
    if (cmd == 1)
      from.update(l, r, value, 0, 0, n - 1);
    else {
      if ((r - l + 1 >= value) &&
          (from.query(l, r - value, 0, 0, n - 1) ==
           Mul(from.query(l + value, r, 0, 0, n - 1),
               base[base.size() - 1 - (l + value - l)])))
        cout << "YES\n";
      else
        cout << "NO\n";
    }
  }
}
signed main() {
  cout << fixed << setprecision(20);
  Solve();
  return 0;
}
