/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<algorithm>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<iostream>
#include<fstream>
#include<numeric>
#include<string>
#include<vector>
#include<cstring>
#include<map>
#include<iterator>
#include<deque>
#include<climits>
#include<complex>

#define S scanf
#define P printf

#define  F(i,a,b) for(int i=a;i<b; i++)
#define FF(i,a,b) for(i=a;i<=b;i++)
#define FI(i,a,b) for((typeof(b)) i=a;i<=b;i++)
#define FR(i, a, b,inc) for(  i = (a); i <= (b); i+=inc )
#define RFR(i, a, b,dec) for(  i = (a); i >= (b); i-=dec )
#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)
#define PR(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++) cout << *it << " "; cout << endl;

#define LL long long int
#define ULL unsigned long long int
#define D double

#define Max(a,b)    (a>b?a:b)
#define Min(a,b)    (a<b?a:b)
#define _Max(a,b,c) Max(a,Max(b,c))
#define _Min(a,b,c) Min(a,Min(b,c))
#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair

#define PCC        cout<<"Case "<<cas++<<": ";
#define PC         printf("Case %d:",cas++);
#define PCN        printf("Case %d:\n",cas++);
#define NL         printf("\n");
#define cp         printf("here\n");

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define Case(a)    printf("Case %d:",a)
#define caseh(a)   printf("Case #%d: ",a)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

int toInt(string s)  { int sm; stringstream ss(s); ss>>sm; return sm; }
int toLlint(string s) { long long int sm; stringstream ss(s); ss>>sm; return sm;}
int cdigittoint(char ch){return ch-'0';}
bool isVowel(char ch){ ch=toupper(ch); if(ch=='A'||ch=='U'||ch=='I'||ch=='O'||ch=='E') return true; return false;}
bool isConst(char ch){if (isalpha(ch) && !isVowel(ch)) return true; return false;}

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 10000019LL
#define Base2 10000079LL
#define Base3 10000103LL
#define MOD1  1000000007LL
#define MOD2  1000000009LL
#define MOD3  1000000021LL
#define LOGX  17

LL B[2][MX];
LL M[2][MX];
LL Sum[2][4*MX],Tree[2][4*MX];
LL Mod[] = {MOD1,MOD3};
int Lazy[4*MX];

char s[MX];

void Init(){
    B[0][0] = B[1][0] = 1;

    for (int i=1;i<MX;i++){
        B[0][i] = (B[0][i-1] * Base1) % MOD1;
        B[1][i] = (B[1][i-1] * Base3) % MOD3;

        M[0][i] = ModInv( B[0][i] , MOD1 );
        M[1][i] = ModInv( B[1][i] , MOD3 );
    }
}

void Build(int idx,int l,int r){
    Lazy[idx] = -1;

    if (l == r){
        for (int i=0;i<2;i++){
            Sum[i][idx] = B[i][l];
            Tree[i][idx] = (( s[l]-'0'+1 ) * Sum[i][idx])%Mod[i];
        }

        return ;
    }

    Build(lft,l,mid);
    Build(rgt,mid+1,r);

    rep(i,0,1)  Sum[i][idx] = (Sum[i][lft] + Sum[i][rgt])%Mod[i], Tree[i][idx] = (Tree[i][lft] + Tree[i][rgt])%Mod[i];
}

void Propagate(int idx,int v){
    Lazy[idx] = v;

    rep(i,0,1)   Tree[i][idx] = ( v * Sum[i][idx] ) % Mod[i];
}

void Update(int idx,int l,int r,int s,int e,int v){
    if (l == s && r == e){
        Propagate(idx,v);
        return ;
    }

    if (Lazy[idx] != -1){
        Propagate(lft,Lazy[idx]);
        Propagate(rgt,Lazy[idx]);
        Lazy[idx] = -1;
    }

    if (e <= mid)       Update(lft,l,mid,s,e,v);
    else if (s > mid)   Update(rgt,mid+1,r,s,e,v);
    else                Update(lft,l,mid,s,mid,v), Update(rgt,mid+1,r,mid+1,e,v);

    rep(i,0,1)          Tree[i][idx] = ( Tree[i][lft] + Tree[i][rgt] )% Mod[i];
}

PLL Query(int idx,int l,int r,int s,int e){
    if ( l == s && r == e ){
        LL p[2];

        rep(i,0,1)  p[i] = ( Tree[i][idx] * M[i][l] ) % Mod[i];

        return MP( p[0],p[1] );
    }

    if ( Lazy[idx] != -1 ){
        Propagate(lft,Lazy[idx]);
        Propagate(rgt,Lazy[idx]);
        Lazy[idx] = -1;
    }

    if (e <= mid)       return Query(lft,l,mid,s,e);
    else if (s > mid)   return Query(rgt,mid+1,r,s,e);
    else{
        PLL q1 = Query(lft,l,mid,s,mid);
        PLL q2 = Query(rgt,mid+1,r,mid+1,e);

        LL p[2];

        p[0] = (q1.X + ( q2.X * B[0][mid+1-s] ))%Mod[0];
        p[1] = (q1.Y + ( q2.Y * B[1][mid+1-s] ))%Mod[1];

        return MP( p[0],p[1] );
    }
}

int main(){
    Init();

    DIII(n,m,k);

    S("%s",s+1);

    Build(1,1,n);

    rep(i,1,m+k){
        DI(cs);
        DIII(l,r,x);

        if (cs == 1)    Update(1,1,n,l,r,x+1);
        else{
            //if (x > (r-l+1)/2)    { puts("NO"); continue; }

            PLL q1 = Query(1,1,n,l,r-x);
            PLL q2 = Query(1,1,n,l+x,r);

            //cout << q1.X << " == " << q2.X << endl;
            //cout << q1.Y << " == " << q2.Y << endl;

            if (q1 == q2)   puts("YES");
            else            puts("NO");
        }
    }
return 0;
}


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<algorithm>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<iostream>
#include<fstream>
#include<numeric>
#include<string>
#include<vector>
#include<cstring>
#include<map>
#include<iterator>
#include<deque>
#include<climits>
#include<complex>

#define S scanf
#define P printf

#define  F(i,a,b) for(int i=a;i<b; i++)
#define FF(i,a,b) for(i=a;i<=b;i++)
#define FI(i,a,b) for((typeof(b)) i=a;i<=b;i++)
#define FR(i, a, b,inc) for(  i = (a); i <= (b); i+=inc )
#define RFR(i, a, b,dec) for(  i = (a); i >= (b); i-=dec )
#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)
#define PR(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++) cout << *it << " "; cout << endl;

#define LL long long int
#define ULL unsigned long long int
#define D double

#define Max(a,b)    (a>b?a:b)
#define Min(a,b)    (a<b?a:b)
#define _Max(a,b,c) Max(a,Max(b,c))
#define _Min(a,b,c) Min(a,Min(b,c))
#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair

#define PCC        cout<<"Case "<<cas++<<": ";
#define PC         printf("Case %d:",cas++);
#define PCN        printf("Case %d:\n",cas++);
#define NL         printf("\n");
#define cp         printf("here\n");

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define Case(a)    printf("Case %d:",a)
#define caseh(a)   printf("Case #%d: ",a)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

int toInt(string s)  { int sm; stringstream ss(s); ss>>sm; return sm; }
int toLlint(string s) { long long int sm; stringstream ss(s); ss>>sm; return sm;}
int cdigittoint(char ch){return ch-'0';}
bool isVowel(char ch){ ch=toupper(ch); if(ch=='A'||ch=='U'||ch=='I'||ch=='O'||ch=='E') return true; return false;}
bool isConst(char ch){if (isalpha(ch) && !isVowel(ch)) return true; return false;}

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 10000019LL
#define Base2 10000079LL
#define Base3 10000103LL
#define MOD1  1000000007LL
#define MOD2  1000000009LL
#define MOD3  1000000021LL
#define LOGX  17

LL B[2][MX];
LL M[2][MX];
LL Sum[2][4*MX],Tree[2][4*MX];
LL Mod[] = {MOD1,MOD3};
int Lazy[4*MX];

char s[MX];

void Init(){
    B[0][0] = B[1][0] = 1;
    Sum[0][0] = Sum[1][0] = 1;

    for (int i=1;i<MX;i++){
        B[0][i] = (B[0][i-1] * Base1) % MOD1;
        B[1][i] = (B[1][i-1] * Base3) % MOD3;

        Sum[0][i] = Sum[0][i-1] + B[0][i];
        Sum[1][i] = Sum[1][i-1] + B[1][i];

        M[0][i] = ModInv( B[0][i] , MOD1 );
        M[1][i] = ModInv( B[1][i] , MOD3 );
    }
}

void Build(int idx,int l,int r){
    Lazy[idx] = -1;

    if (l == r){
        for (int i=0;i<2;i++){
            Tree[i][idx] = ( s[l]-'0'+1 )%Mod[i];
        }

        return ;
    }

    Build(lft,l,mid);
    Build(rgt,mid+1,r);

    rep(i,0,1){
        Tree[i][idx] = (Tree[i][lft] + B[i][mid+1-l]*Tree[i][rgt])%Mod[i];
    }
}

void Propagate(int idx,int l,int r,int v){
    Lazy[idx] = v;

    rep(i,0,1)   Tree[i][idx] = ( v * Sum[i][r-l] ) % Mod[i];
}

void Update(int idx,int l,int r,int s,int e,int v){
    if (l == s && r == e){
        Propagate(idx,l,r,v);
        return ;
    }

    if (Lazy[idx] != -1){
        Propagate(lft,l,mid,Lazy[idx]);
        Propagate(rgt,mid+1,r,Lazy[idx]);
        Lazy[idx] = -1;
    }

    if (e <= mid)       Update(lft,l,mid,s,e,v);
    else if (s > mid)   Update(rgt,mid+1,r,s,e,v);
    else                Update(lft,l,mid,s,mid,v), Update(rgt,mid+1,r,mid+1,e,v);

    rep(i,0,1)          Tree[i][idx] = ( Tree[i][lft] + B[i][mid+1-l]*Tree[i][rgt] )% Mod[i];
}

PLL Query(int idx,int l,int r,int s,int e){
    if ( l == s && r == e ){
        return MP( Tree[0][idx],Tree[1][idx] );
    }

    if ( Lazy[idx] != -1 ){
        Propagate(lft,l,mid,Lazy[idx]);
        Propagate(rgt,mid+1,r,Lazy[idx]);
        Lazy[idx] = -1;
    }

    if (e <= mid)       return Query(lft,l,mid,s,e);
    else if (s > mid)   return Query(rgt,mid+1,r,s,e);
    else{
        PLL q1 = Query(lft,l,mid,s,mid);
        PLL q2 = Query(rgt,mid+1,r,mid+1,e);

        LL p[2];

        p[0] = (q1.X + ( q2.X * B[0][mid+1-s] ))%Mod[0];
        p[1] = (q1.Y + ( q2.Y * B[1][mid+1-s] ))%Mod[1];

        return MP( p[0],p[1] );
    }
}

int main(){
    Init();

    DIII(n,m,k);

    S("%s",s+1);

    Build(1,1,n);

    rep(i,1,m+k){
        DI(cs);
        DIII(l,r,x);

        if (cs == 1)    Update(1,1,n,l,r,x+1);
        else{
            if (x > (r-l))    { puts("YES"); continue; }

            PLL q1 = Query(1,1,n,l,r-x);
            PLL q2 = Query(1,1,n,l+x,r);

            //cout << q1.X << " == " << q2.X << endl;
            //cout << q1.Y << " == " << q2.Y << endl;

            if (q1 == q2)   puts("YES");
            else            puts("NO");
        }
    }
return 0;
}


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<algorithm>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<iostream>
#include<fstream>
#include<numeric>
#include<string>
#include<vector>
#include<cstring>
#include<map>
#include<iterator>
#include<deque>
#include<climits>
#include<complex>

#define S scanf
#define P printf

#define  F(i,a,b) for(int i=a;i<b; i++)
#define FF(i,a,b) for(i=a;i<=b;i++)
#define FI(i,a,b) for((typeof(b)) i=a;i<=b;i++)
#define FR(i, a, b,inc) for(  i = (a); i <= (b); i+=inc )
#define RFR(i, a, b,dec) for(  i = (a); i >= (b); i-=dec )
#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)
#define PR(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++) cout << *it << " "; cout << endl;

#define LL long long int
#define ULL unsigned long long int
#define D double

#define Max(a,b)    (a>b?a:b)
#define Min(a,b)    (a<b?a:b)
#define _Max(a,b,c) Max(a,Max(b,c))
#define _Min(a,b,c) Min(a,Min(b,c))
#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair

#define PCC        cout<<"Case "<<cas++<<": ";
#define PC         printf("Case %d:",cas++);
#define PCN        printf("Case %d:\n",cas++);
#define NL         printf("\n");
#define cp         printf("here\n");

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define Case(a)    printf("Case %d:",a)
#define caseh(a)   printf("Case #%d: ",a)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

int toInt(string s)  { int sm; stringstream ss(s); ss>>sm; return sm; }
int toLlint(string s) { long long int sm; stringstream ss(s); ss>>sm; return sm;}
int cdigittoint(char ch){return ch-'0';}
bool isVowel(char ch){ ch=toupper(ch); if(ch=='A'||ch=='U'||ch=='I'||ch=='O'||ch=='E') return true; return false;}
bool isConst(char ch){if (isalpha(ch) && !isVowel(ch)) return true; return false;}

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define PUL pair< ULL , ULL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 13ULL
#define Base2 19ULL
#define Base3 10000103LL
#define MOD1  1000000007LL
#define MOD2  1000000009LL
#define MOD3  1000000021LL
#define LOGX  17

ULL B1[MX],B2[MX];
ULL S1[MX],S2[MX];
ULL Tree[2][4*MX];
int Lazy[4*MX];
char s[MX];

void Init(){
    B1[0] = B2[0] = S1[0] = S2[0] = 1;

    for (int i=1;i<MX;i++){
        B1[i] = B1[i-1] * Base1;
        B2[i] = B2[i-1] * Base2;

        S1[i] = S1[i-1] + B1[i];
        S2[i] = S2[i-1] + B2[i];
    }
}

void Propagate(int idx,int l,int r,int v){
    Lazy[idx] = v;

    Tree[0][idx] = S1[r-l] * v;
    Tree[1][idx] = S2[r-l] * v;
}

void Update(int idx,int l,int r,int s,int e,int v){
    if (l == s && r == e){
        Propagate(idx,l,r,v);
        return;
    }

    if (Lazy[idx]){
        Propagate(lft,l,mid,Lazy[idx]);
        Propagate(rgt,mid+1,r,Lazy[idx]);
        Lazy[idx] = 0;
    }

    if (e <= mid)       Update(lft,l,mid,s,e,v);
    else if (s > mid)   Update(rgt,mid+1,r,s,e,v);
    else                Update(lft,l,mid,s,mid,v),Update(rgt,mid+1,r,mid+1,e,v);

    Tree[0][idx] = Tree[0][lft] + B1[mid+1-l]*Tree[0][rgt];
    Tree[1][idx] = Tree[1][lft] + B2[mid+1-l]*Tree[1][rgt];
}

PUL Query(int idx,int l,int r,int s,int e){
    if (l == s && r == e)       return MP( Tree[0][idx],Tree[1][idx] );

    if (Lazy[idx]){
        Propagate(lft,l,mid,Lazy[idx]);
        Propagate(rgt,mid+1,r,Lazy[idx]);
        Lazy[idx] = 0;
    }

    if (e <= mid)               return Query(lft,l,mid,s,e);
    else if (s > mid)           return Query(rgt,mid+1,r,s,e);
    else {
        PUL q1 = Query(lft,l,mid,s,mid);
        PUL q2 = Query(rgt,mid+1,r,mid+1,e);

        PUL q;

        q.X = q1.X + B1[mid+1-s]*q2.X;
        q.Y = q1.Y + B2[mid+1-s]*q2.Y;

        return q;
    }
}

int main(){
    Init();

    DIII(n,m,k);

    S("%s",s+1);

    for (int i=1;i<=n;i++)      Update(1,1,n,i,i,s[i]-'0'+1);

    rep(i,1,m+k){
        DI(cs);
        DIII(l,r,x);

        if (cs == 1)    Update(1,1,n,l,r,x+1);
        else{
            if (l == r)       { puts("YES"); continue; }
            if (x > (r-l))    { puts("YES"); continue; }

            PUL q1 = Query(1,1,n,l,r-x);
            PUL q2 = Query(1,1,n,l+x,r);

            //cout << q1.X << " == " << q2.X << endl;
            //cout << q1.Y << " == " << q2.Y << endl;

            if (q1 == q2)   puts("YES");
            else            puts("NO");
        }
    }
return 0;
}


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<algorithm>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<iostream>
#include<fstream>
#include<numeric>
#include<string>
#include<vector>
#include<cstring>
#include<map>
#include<iterator>
#include<deque>
#include<climits>
#include<complex>

#define S scanf
#define P printf

#define  F(i,a,b) for(int i=a;i<b; i++)
#define FF(i,a,b) for(i=a;i<=b;i++)
#define FI(i,a,b) for((typeof(b)) i=a;i<=b;i++)
#define FR(i, a, b,inc) for(  i = (a); i <= (b); i+=inc )
#define RFR(i, a, b,dec) for(  i = (a); i >= (b); i-=dec )
#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)
#define PR(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++) cout << *it << " "; cout << endl;

#define LL long long int
#define ULL unsigned long long int
#define D double

#define Max(a,b)    (a>b?a:b)
#define Min(a,b)    (a<b?a:b)
#define _Max(a,b,c) Max(a,Max(b,c))
#define _Min(a,b,c) Min(a,Min(b,c))
#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair

#define PCC        cout<<"Case "<<cas++<<": ";
#define PC         printf("Case %d:",cas++);
#define PCN        printf("Case %d:\n",cas++);
#define NL         printf("\n");
#define cp         printf("here\n");

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define Case(a)    printf("Case %d:",a)
#define caseh(a)   printf("Case #%d: ",a)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

int toInt(string s)  { int sm; stringstream ss(s); ss>>sm; return sm; }
int toLlint(string s) { long long int sm; stringstream ss(s); ss>>sm; return sm;}
int cdigittoint(char ch){return ch-'0';}
bool isVowel(char ch){ ch=toupper(ch); if(ch=='A'||ch=='U'||ch=='I'||ch=='O'||ch=='E') return true; return false;}
bool isConst(char ch){if (isalpha(ch) && !isVowel(ch)) return true; return false;}

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 10000019LL
#define Base2 10000079LL
#define Base3 10000103LL
#define MOD1  1000000007LL
#define MOD2  1000000009LL
#define MOD3  1000000021LL
#define LOGX  17

LL B[2][MX];
LL M[2][MX];
LL Sum[2][4*MX],Tree[2][4*MX];
LL Mod[] = {MOD1,MOD3};
int Lazy[4*MX];

char s[MX];

void Init(){
    B[0][0] = B[1][0] = 1;

    for (int i=1;i<MX;i++){
        B[0][i] = (B[0][i-1] * Base1) % MOD1;
        B[1][i] = (B[1][i-1] * Base3) % MOD3;

        M[0][i] = ModInv( B[0][i] , MOD1 );
        M[1][i] = ModInv( B[1][i] , MOD3 );
    }
}

void Build(int idx,int l,int r){
    Lazy[idx] = -1;

    if (l == r){
        for (int i=0;i<2;i++){
            Sum[i][idx] = B[i][l];
            Tree[i][idx] = (( s[l]-'0'+1 ) * Sum[i][idx])%Mod[i];
        }

        return ;
    }

    Build(lft,l,mid);
    Build(rgt,mid+1,r);

    rep(i,0,1)  Sum[i][idx] = (Sum[i][lft] + Sum[i][rgt])%Mod[i], Tree[i][idx] = (Tree[i][lft] + Tree[i][rgt])%Mod[i];
}

void Propagate(int idx,int v){
    Lazy[idx] = v;

    rep(i,0,1)   Tree[i][idx] = ( v * Sum[i][idx] ) % Mod[i];
}

void Update(int idx,int l,int r,int s,int e,int v){
    if (l == s && r == e){
        Propagate(idx,v);
        return ;
    }

    if (Lazy[idx] != -1){
        Propagate(lft,Lazy[idx]);
        Propagate(rgt,Lazy[idx]);
        Lazy[idx] = -1;
    }

    if (e <= mid)       Update(lft,l,mid,s,e,v);
    else if (s > mid)   Update(rgt,mid+1,r,s,e,v);
    else                Update(lft,l,mid,s,mid,v), Update(rgt,mid+1,r,mid+1,e,v);

    rep(i,0,1)          Tree[i][idx] = ( Tree[i][lft] + Tree[i][rgt] )% Mod[i];
}

PLL Query(int idx,int l,int r,int s,int e){
    if ( l == s && r == e ){
        LL p[2];

        rep(i,0,1)  p[i] = ( Tree[i][idx] * M[i][l] ) % Mod[i];

        return MP( p[0],p[1] );
    }

    if ( Lazy[idx] != -1 ){
        Propagate(lft,Lazy[idx]);
        Propagate(rgt,Lazy[idx]);
        Lazy[idx] = -1;
    }

    if (e <= mid)       return Query(lft,l,mid,s,e);
    else if (s > mid)   return Query(rgt,mid+1,r,s,e);
    else{
        PLL q1 = Query(lft,l,mid,s,mid);
        PLL q2 = Query(rgt,mid+1,r,mid+1,e);

        LL p[2];

        p[0] = (q1.X + ( q2.X * B[0][mid+1-s] ))%Mod[0];
        p[1] = (q1.Y + ( q2.Y * B[1][mid+1-s] ))%Mod[1];

        return MP( p[0],p[1] );
    }
}

int main(){
    Init();

    DIII(n,m,k);

    S("%s",s+1);

    Build(1,1,n);

    rep(i,1,m+k){
        DI(cs);
        DIII(l,r,x);

        if (cs == 1)    Update(1,1,n,l,r,x+1);
        else{
            if (x > (r-l))    { puts("YES"); continue; }

            PLL q1 = Query(1,1,n,l,r-x);
            PLL q2 = Query(1,1,n,l+x,r);

            //cout << q1.X << " == " << q2.X << endl;
            //cout << q1.Y << " == " << q2.Y << endl;

            if (q1 == q2)   puts("YES");
            else            puts("NO");
        }
    }
return 0;
}


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<algorithm>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<iostream>
#include<fstream>
#include<numeric>
#include<string>
#include<vector>
#include<cstring>
#include<map>
#include<iterator>
#include<deque>
#include<climits>
#include<complex>

#define S scanf
#define P printf

#define  F(i,a,b) for(int i=a;i<b; i++)
#define FF(i,a,b) for(i=a;i<=b;i++)
#define FI(i,a,b) for((typeof(b)) i=a;i<=b;i++)
#define FR(i, a, b,inc) for(  i = (a); i <= (b); i+=inc )
#define RFR(i, a, b,dec) for(  i = (a); i >= (b); i-=dec )
#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)
#define PR(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++) cout << *it << " "; cout << endl;

#define LL long long int
#define ULL unsigned long long int
#define D double

#define Max(a,b)    (a>b?a:b)
#define Min(a,b)    (a<b?a:b)
#define _Max(a,b,c) Max(a,Max(b,c))
#define _Min(a,b,c) Min(a,Min(b,c))
#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair

#define PCC        cout<<"Case "<<cas++<<": ";
#define PC         printf("Case %d:",cas++);
#define PCN        printf("Case %d:\n",cas++);
#define NL         printf("\n");
#define cp         printf("here\n");

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define Case(a)    printf("Case %d:",a)
#define caseh(a)   printf("Case #%d: ",a)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

int toInt(string s)  { int sm; stringstream ss(s); ss>>sm; return sm; }
int toLlint(string s) { long long int sm; stringstream ss(s); ss>>sm; return sm;}
int cdigittoint(char ch){return ch-'0';}
bool isVowel(char ch){ ch=toupper(ch); if(ch=='A'||ch=='U'||ch=='I'||ch=='O'||ch=='E') return true; return false;}
bool isConst(char ch){if (isalpha(ch) && !isVowel(ch)) return true; return false;}

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define PUL pair< ULL , ULL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 13ULL
#define Base2 19ULL
#define Base3 10000103LL
#define MOD1  1000000007LL
#define MOD2  1000000009LL
#define MOD3  1000000021LL
#define LOGX  17

ULL B1[MX],B2[MX];
ULL S1[MX],S2[MX];
ULL Tree[2][4*MX];
int Lazy[4*MX];
char s[MX];

void Init(){
    B1[0] = B2[0] = S1[0] = S2[0] = 1;

    for (int i=1;i<MX;i++){
        B1[i] = (B1[i-1] * Base1)%MOD1;
        B2[i] = (B2[i-1] * Base2)%MOD2;

        S1[i] = (S1[i-1] + B1[i])%MOD1;
        S2[i] = (S2[i-1] + B2[i])%MOD2;
    }
}

void Propagate(int idx,int l,int r,int v){
    Lazy[idx] = v;

    Tree[0][idx] = (S1[r-l] * v)%MOD1;
    Tree[1][idx] = (S2[r-l] * v)%MOD2;
}

void Update(int idx,int l,int r,int s,int e,int v){
    if (l == s && r == e){
        Propagate(idx,l,r,v);
        return;
    }

    if (Lazy[idx]){
        Propagate(lft,l,mid,Lazy[idx]);
        Propagate(rgt,mid+1,r,Lazy[idx]);
        Lazy[idx] = 0;
    }

    if (e <= mid)       Update(lft,l,mid,s,e,v);
    else if (s > mid)   Update(rgt,mid+1,r,s,e,v);
    else                Update(lft,l,mid,s,mid,v),Update(rgt,mid+1,r,mid+1,e,v);

    Tree[0][idx] = (Tree[0][lft] + (B1[mid+1-l]*Tree[0][rgt])%MOD1)%MOD1;
    Tree[1][idx] = (Tree[1][lft] + (B2[mid+1-l]*Tree[1][rgt])%MOD2)%MOD2;
}

PUL Query(int idx,int l,int r,int s,int e){
    if (l == s && r == e)       return MP( Tree[0][idx],Tree[1][idx] );

    if (Lazy[idx]){
        Propagate(lft,l,mid,Lazy[idx]);
        Propagate(rgt,mid+1,r,Lazy[idx]);
        Lazy[idx] = 0;
    }

    if (e <= mid)               return Query(lft,l,mid,s,e);
    else if (s > mid)           return Query(rgt,mid+1,r,s,e);
    else {
        PUL q1 = Query(lft,l,mid,s,mid);
        PUL q2 = Query(rgt,mid+1,r,mid+1,e);

        PUL q;

        q.X = (q1.X + (B1[mid+1-s]*q2.X)%MOD1)%MOD1;
        q.Y = (q1.Y + (B2[mid+1-s]*q2.Y)%MOD2)%MOD2;

        return q;
    }
}

int main(){
    Init();

    DIII(n,m,k);

    S("%s",s+1);

    for (int i=1;i<=n;i++)      Update(1,1,n,i,i,s[i]-'0'+1);

    rep(i,1,m+k){
        DI(cs);
        DIII(l,r,x);

        if (cs == 1)    Update(1,1,n,l,r,x+1);
        else{
            if (l == r)       { puts("YES"); continue; }
            if (x > (r-l))    { puts("YES"); continue; }

            PUL q1 = Query(1,1,n,l,r-x);
            PUL q2 = Query(1,1,n,l+x,r);

            //cout << q1.X << " == " << q2.X << endl;
            //cout << q1.Y << " == " << q2.Y << endl;

            if (q1 == q2)   puts("YES");
            else            puts("NO");
        }
    }
return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef long long ll;
typedef pair <int, ll> pil;

const int base = 233;
const int mod = 1e9 + 7;
const ll INF = 1e18;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<1], len[N<<1];
ll pw[N<<1], dp[N<<1], tree[N<<1];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 3;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef long long ull;
typedef pair <int, ull> pil;

const int base = 277;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef long long ll;
typedef pair <int, ll> pil;

const int base = 233;
const int mod = 1e9 + 7;
const ll INF = 1e18;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, setv[N], len[N];
ll pw[N], dp[N], tree[N<<1], a[N];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 311;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 129973;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 101;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = (tree[le] * pw[len[ri]] + tree[ri]) % mod;
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1] % mod;
        tree[ri] = setv[v] * dp[len[ri]-1] % mod;
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1] % mod;
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, (x.Y * pw[y.X] + y.Y) % mod);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1] % mod, dp[i] = (dp[i-1] + pw[i]) % mod;
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 1299;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 233;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = (tree[le] * pw[len[ri]] + tree[ri]) % mod;
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1] % mod;
        tree[ri] = setv[v] * dp[len[ri]-1] % mod;
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1] % mod;
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, (x.Y * pw[y.X] + y.Y) % mod);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1] % mod, dp[i] = (dp[i-1] + pw[i]) % mod;
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 277;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 101;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define gc getchar
#define pc putchar
#define pb push_back
#define X first
#define Y second
#define Mod(x) (((x) % mod + mod) % mod)
#define all(x) x.begin(), x.end()

typedef pair <int, int> pii;
typedef unsigned long long ull;
typedef pair <int, ull> pil;

const int base = 233;
const int mod = 1e9 + 7;
const double ep = 1e-7;
const double pi = 3.14159265358979323846264338327950288L;

template <class T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}

template <class T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}

int n, m, k, a[N], setv[N<<2], len[N<<2];
ull pw[N<<2], dp[N<<2], tree[N<<2];
char s[N];

#define le v << 1
#define ri v << 1 ^ 1
#define mi (vl + vr >> 1)

void up(int v) {
    tree[v] = tree[le] * pw[len[ri]] + tree[ri];
}

void down(int v) {
    if (setv[v] >= 0) {
        setv[le] = setv[ri] = setv[v];
        tree[le] = setv[v] * dp[len[le]-1];
        tree[ri] = setv[v] * dp[len[ri]-1];
        setv[v] = -1;
    }
}

void build(int v, int vl, int vr) {
    len[v] = vr - vl + 1;
    if (vl == vr) {tree[v] = a[vl]; return;}
    build(le, vl, mi);
    build(ri, mi + 1, vr);
    up(v);
}

void modify(int v, int vl, int vr, int l, int r, int c) {
    if (vl > r || l > vr) return;
    if (l <= vl && vr <= r) {
        setv[v] = c;
        tree[v] = c * dp[len[v]-1];
        return;
    }
    down(v);
    modify(le, vl, mi, l, r, c);
    modify(ri, mi + 1, vr, l, r, c);
    up(v);
}

pil query(int v, int vl, int vr, int l, int r) {
    if (vl > r || l > vr) return pil(0, 0);
    if (l <= vl && vr <= r) return pil(len[v], tree[v]);
    down(v);
    pil x = query(le, vl, mi, l, r), y = query(ri, mi + 1, vr, l, r);
    return pil(x.X + y.X, x.Y * pw[y.X] + y.Y);
}

int main() {
    pw[0] = dp[0] = 1;
    for (int i = 1; i < N; i ++) pw[i] = base * pw[i-1], dp[i] = dp[i-1] + pw[i];
    scanf("%d %d %d %s", &n, &m, &k, s + 1);
    m += k;
    memset(setv, -1, sizeof setv);
    for (int i = 1; i <= n; i ++) a[i] = s[i] - '0';
    build(1, 1, n);
    while (m --) {
        int t, l, r, c;
        scanf("%d %d %d %d", &t, &l, &r, &c);
        if (t == 1) modify(1, 1, n, l, r, c);
        else puts(query(1, 1, n, l, r - c) == query(1, 1, n, l + c, r) ? "YES" : "NO");
    }

    return 0;
}


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

typedef long long ll;

const int NPRIME = 2;
const int P1 = 1e9 + 7, P2 = 1e9 + 9, P3 = 1e9 + 21;
const int primes[] = {P1, P2, P3};

const int BASE = 1009;
const int MAXL = 1e5 + 100;

struct mods {
    ll vals[3];

    mods(ll value = 0) {
        for (int i = 0; i < NPRIME; i++)
            vals[i] = value % primes[i];
    }

    bool operator==(const mods &h) {
        for (int i = 0; i < NPRIME; i++)
            if(vals[i] != h.vals[i])
                return false;
        return true;
    }

    mods operator*(const mods &h) {
        mods res;
        for (int i = 0; i < NPRIME; i++)
            res.vals[i] = (vals[i] * h.vals[i]) % primes[i];
        return res;
    }

    mods operator*(ll m) {
        return (*this) * mods(m);
    }

    mods operator+(const mods &h) {
        mods res;
        for (int i = 0; i < NPRIME; i++)
            res.vals[i] = (vals[i] + h.vals[i]) % primes[i];
        return res;
    }

    mods operator+(ll a) {
        return (*this) + mods(a);
    }
};

mods powers[MAXL], powsum[MAXL];

void init() {
    powers[0] = mods(1);
    powsum[0] = powers[0];

    for(int i=1; i<MAXL; i++) {
        powers[i] = powers[i-1] * BASE;
        powsum[i] = powsum[i-1] + powers[i];
    }
}

template<typename T, typename U> struct seg_tree_lazy {
    int S, H;

    T def;
    vector<T> value;

    U noop;
    vector<U> prop;

    seg_tree_lazy<T, U>(int _S, T _def = T(), U _noop = U()) {
        S = _S, def = _def, noop = _noop;
        assert(__builtin_popcount(S) == 1);
        H = 32 - __builtin_clz(S);

        value.resize(2 * S + 1, def);
        prop.resize(2 * S + 1, noop);
    }

    void apply(int i, U update) {
        value[i] = update(value[i]);
        if(i < S) prop[i] = prop[i] + update;
    }

    void rebuild(int i) {
        for (int l = i/2; l; l /= 2) {
            T combined = value[2*l] + value[2*l+1];
            value[l] = prop[l](combined);
        }
    }

    void propagate(int i) {
        for (int h = H; h > 0; h--) {
            int l = i >> h;
            if (prop[l] != noop) {
                apply(2*l, prop[l]);
                apply(2*l+1, prop[l]);
                prop[l] = noop;
            }
        }
    }

    void upd(int i, int j, U update) {
        i += S, j += S;
        propagate(i), propagate(j);

        for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
            if((l&1) == 1) apply(l++, update);
            if((r&1) == 0) apply(r--, update);
        }

        rebuild(i), rebuild(j);
    }

    T query(int i, int j){
        i += S, j += S;
        propagate(i), propagate(j);

        T resl = def, resr = def;
        for(; i <= j; i /= 2, j /= 2){
            if((i&1) == 1) resl = resl + value[i++];
            if((j&1) == 0) resr = value[j--] + resr;
        }
        return resl + resr;
    }
};

struct node {
    int l;
    mods hash;

    node operator+(const node &o) {
        return { l + o.l, hash * powers[o.l] + o.hash };
    }
};

struct update {
    int v;

    node operator()(node &n) {
        if (v == -1) return n;
        return { n.l, powsum[n.l-1] * v };
    }

    update operator+(const update &o) {
        return o;
    }

    bool operator!=(const update &o) {
        return v != o.v;
    }
};

int N, M, K;
string input;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0), cout.precision(15);

    init();

    cin >> N >> M >> K;
    cin >> input;

    int S = 1; while(S < N) S *= 2;
    seg_tree_lazy<node, update> st(S, {0, 0}, {-1});

    for (int i = 2 * S - 1; i > 0; i--) {
        if(i < S) st.value[i] = st.value[2*i] + st.value[2*i+1];
        else if(i < S + N) st.value[i] = {1, mods(input[i-S])};
        else st.value[i] = {1, mods(0)};
    }

    for (int q = 0; q < M + K; q++) {
        int t, l, r, v;
        cin >> t >> l >> r >> v;

        if (t == 1) {
            st.upd(l - 1, r - 1, { '0' + v });
        } else {
            if (l > r - v) {
                cout << "YES\n";
                continue;
            }

            l--, r--;
            mods h1 = st.query(l, r - v).hash;
            mods h2 = st.query(l + v, r).hash;

            if (h1 == h2) cout << "YES\n";
            else cout << "NO\n";
        }
    }
}


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

typedef long long ll;

const int NPRIME = 2;
const int P1 = 1e9+7, P2 = 1e9+9, P3 = 1e9+21;
const int primes[3] = { P1, P2, P3 };

struct mods {
    int vals[NPRIME];

    mods(ll value = 0) {
        for (int i = 0; i < NPRIME; i++)
            vals[i] = value % primes[i];
    }

    #define combine(h, op) \
        mods res; \
        for (int i = 0; i < NPRIME; i++) \
            res.vals[i] = (vals[i] op h.vals[i]) % primes[i]; \
        return res;

    bool operator==(const mods &h) { return !memcmp(this, &h, sizeof(mods)); }
    mods operator*(const mods &h) { combine(h, * 1ll *); }
    mods operator+(const mods &h) { combine(h, +); }

    mods operator*(ll m) { return (*this) * mods(m); }
    mods operator+(ll a) { return (*this) + mods(a); }
};

const int BASE = 1009;
const int MAXL = 1e5 + 100;
mods powers[MAXL], powsum[MAXL];

void init() {
    powers[0] = mods(1);
    powsum[0] = powers[0];

    for(int i=1; i<MAXL; i++) {
        powers[i] = powers[i-1] * BASE;
        powsum[i] = powsum[i-1] + powers[i];
    }
}

template<typename T, typename U> struct seg_tree_lazy {
    int S, H;

    T def;
    vector<T> value;

    U noop;
    vector<U> prop;

    void init(int _S) {
        for (S = 1, H = 1; S < _S; ) S *= 2, H++;
        value.resize(2*S, def);
        prop.resize(2*S, noop);
    }

    seg_tree_lazy<T, U>(int _S, T _def = T(), U _noop = U()) {
        def = _def, noop = _noop;
        init(_S);
    }

    seg_tree_lazy<T, U>(vector<T> &leaves, T _def = T(), U _noop = U()) {
        def = _def, noop = _noop;

        init(leaves.size());
        copy(leaves.begin(), leaves.end(), value.begin() + S);

        for (int i = S - 1; i > 0; i--)
            value[i] = value[2 * i] + value[2 * i + 1];
    }

    void apply(int i, U update) {
        value[i] = update(value[i]);
        if(i < S) prop[i] = prop[i] + update;
    }

    void rebuild(int i) {
        for (int l = i/2; l; l /= 2) {
            value[i] = value[2*l] + value[2*l+1];
            value[i] = prop[i](value[i]);
        }
    }

    void propagate(int i) {
        for (int h = H; h > 0; h--) {
            int l = i >> h;
            if (memcmp(&prop[l], &noop, sizeof(U))) {
                apply(2*l, prop[l]);
                apply(2*l+1, prop[l]);
                prop[l] = noop;
            }
        }
    }

    void upd(int i, int j, U update) {
        i += S, j += S;
        propagate(i), propagate(j);

        for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
            if((l&1) == 1) apply(l++, update);
            if((r&1) == 0) apply(r--, update);
        }

        rebuild(i), rebuild(j);
    }

    T query(int i, int j){
        i += S, j += S;
        propagate(i), propagate(j);

        T resl = def, resr = def;
        for(; i <= j; i /= 2, j /= 2){
            if((i&1) == 1) resl = resl + value[i++];
            if((j&1) == 0) resr = value[j--] + resr;
        }
        return resl + resr;
    }
};

struct node {
    int l;
    mods hash;

    node operator+(const node &o) {
        return { l + o.l, hash * powers[o.l] + o.hash };
    }
};

struct update {
    int v;

    node operator()(node &n) {
        if (v == -1) return n;
        return { n.l, powsum[n.l-1] * v };
    }

    update operator+(const update &o) {
        return o;
    }

    bool operator!=(const update &o) {
        return v != o.v;
    }
};

int N, M, K;
string input;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0), cout.precision(15);

    init();

    cin >> N >> M >> K;
    cin >> input;

    vector<node> leaves;
    for (char c : input)
        leaves.push_back({1, mods(c)});

    seg_tree_lazy<node, update> st(leaves, {0, 0}, {-1});

    for (int q = 0; q < M + K; q++) {
        int t, l, r, v;
        cin >> t >> l >> r >> v;

        if (t == 1) {
            st.upd(l - 1, r - 1, { '0' + v });
        } else {
            if (l > r - v) {
                cout << "YES\n";
                continue;
            }

            l--, r--;
            mods h1 = st.query(l, r - v).hash;
            mods h2 = st.query(l + v, r).hash;

            if (h1 == h2) cout << "YES\n";
            else cout << "NO\n";
        }
    }
}


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

typedef long long ll;

template<typename T, typename U> struct seg_tree_lazy {
    int S, H;

    T zero;
    vector<T> value;

    U noop;
    vector<bool> dirty;
    vector<U> prop;

    seg_tree_lazy<T, U>(int _S, T _zero = T(), U _noop = U()) {
        zero = _zero, noop = _noop;
        for (S = 1, H = 1; S < _S; ) S *= 2, H++;

        value.resize(2*S, zero);
        dirty.resize(2*S, false);
        prop.resize(2*S, noop);
    }

    void set_leaves(vector<T> &leaves) {
        copy(leaves.begin(), leaves.end(), value.begin() + S);
        fill(value.begin() + S + leaves.size(), value.end(), zero);

        for (int i = S - 1; i > 0; i--)
            value[i] = value[2 * i] + value[2 * i + 1];
    }

    void apply(int i, U &update) {
        value[i] = update(value[i]);
        if(i < S) {
            prop[i] = prop[i] + update;
            dirty[i] = true;
        }
    }

    void rebuild(int i) {
        for (int l = i/2; l; l /= 2) {
            T combined = value[2*l] + value[2*l+1];
            value[l] = prop[l](combined);
        }
    }

    void propagate(int i) {
        for (int h = H; h > 0; h--) {
            int l = i >> h;

            if (dirty[l]) {
                apply(2*l, prop[l]);
                apply(2*l+1, prop[l]);

                prop[l] = noop;
                dirty[l] = false;
            }
        }
    }

    void upd(int i, int j, U update) {
        i += S, j += S;
        propagate(i), propagate(j);

        for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
            if((l&1) == 1) apply(l++, update);
            if((r&1) == 0) apply(r--, update);
        }

        rebuild(i), rebuild(j);
    }

    T query(int i, int j){
        i += S, j += S;
        propagate(i), propagate(j);

        T res_left = zero, res_right = zero;
        for(; i <= j; i /= 2, j /= 2){
            if((i&1) == 1) res_left = res_left + value[i++];
            if((j&1) == 0) res_right = value[j--] + res_right;
        }
        return res_left + res_right;
    }
};

const int NPRIME = 3;
const int P1 = 1e9+7, P2 = 1e9+9, P3 = 1e9+21;
const int primes[3] = { P1, P2, P3 };

struct mods {
    int vals[NPRIME];

    mods(ll value = 0) {
        for (int i = 0; i < NPRIME; i++)
            vals[i] = value % primes[i];
    }

    #define combine(h, op) \
        mods res; \
        for (int i = 0; i < NPRIME; i++) \
            res.vals[i] = (vals[i] op h.vals[i]) % primes[i]; \
        return res;

    bool operator==(const mods &h) { return !memcmp(this, &h, sizeof(mods)); }
    mods operator*(const mods &h) { combine(h, * 1ll *); }
    mods operator+(const mods &h) { combine(h, +); }

    mods operator*(ll m) { return (*this) * mods(m); }
    mods operator+(ll a) { return (*this) + mods(a); }
};

const int BASE = 1009;
const int MAXL = 1e5 + 100;
mods powers[MAXL], powsum[MAXL];

void init() {
    powers[0] = mods(1);
    powsum[0] = powers[0];

    for(int i=1; i<MAXL; i++) {
        powers[i] = powers[i-1] * BASE;
        powsum[i] = powsum[i-1] + powers[i];
    }
}

struct node {
    int l;
    mods hash;

    node operator+(const node &o) {
        return { l + o.l, hash * powers[o.l] + o.hash };
    }
};

struct update {
    int v;

    node operator()(node &n) {
        if (v == -1) return n;
        return { n.l, powsum[n.l-1] * v };
    }

    update operator+(const update &o) {
        return o;
    }
};

int N, M, K;
string input;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0), cout.precision(15);

    init();

    cin >> N >> M >> K;
    cin >> input;

    seg_tree_lazy<node, update> st(N, {0, 0}, {-1});

    vector<node> leaves;
    for (char c : input)
        leaves.push_back({1, mods(c)});
    st.set_leaves(leaves);

    for (int q = 0; q < M + K; q++) {
        int t, l, r, v;
        cin >> t >> l >> r >> v;
        l--, r--;

        if (t == 1) {
            st.upd(l, r, { '0' + v });
        } else {
            if (l > r - v) {
                cout << "YES\n";
                continue;
            }

            mods h1 = st.query(l, r - v).hash;
            mods h2 = st.query(l + v, r).hash;

            if (h1 == h2) cout << "YES\n";
            else cout << "NO\n";
        }
    }
}


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

typedef long long ll;

template<typename T, typename U> struct seg_tree_lazy {
    int S, H;

    T def, zero;
    vector<T> value;

    U noop;
    vector<U> prop;

    void build() {
        for (int i = S - 1; i > 0; i--)
            value[i] = value[2 * i] + value[2 * i + 1];
    }

    void init(int _S) {
        for (S = 1, H = 1; S < _S; ) S *= 2, H++;
        value.resize(2*S, zero);
        prop.resize(2*S, noop);

        fill(value.begin() + S, value.begin() + S + _S, def);
        build();
    }

    seg_tree_lazy<T, U>(int _S, T _def = T(), T _zero = T(), U _noop = U()) {
        def = _def, zero = _zero, noop = _noop;
        init(_S);
    }

    void set_leaves(vector<T> &leaves) {
        copy(leaves.begin(), leaves.end(), value.begin() + S);
        fill(value.begin() + S + leaves.size(), value.end(), zero);
        build();
    }

    void apply(int i, U update) {
        value[i] = update(value[i]);
        if(i < S) prop[i] = prop[i] + update;
    }

    void rebuild(int i) {
        for (int l = i/2; l; l /= 2) {
            T combined = value[2*l] + value[2*l+1];
            value[l] = prop[l](combined);
        }
    }

    void propagate(int i) {
        for (int h = H; h > 0; h--) {
            int l = i >> h;
            if (memcmp(&prop[l], &noop, sizeof(U))) {
                apply(2*l, prop[l]);
                apply(2*l+1, prop[l]);
                prop[l] = noop;
            }
        }
    }

    void upd(int i, int j, U update) {
        i += S, j += S;
        propagate(i), propagate(j);

        for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
            if((l&1) == 1) apply(l++, update);
            if((r&1) == 0) apply(r--, update);
        }

        rebuild(i), rebuild(j);
    }

    T query(int i, int j){
        i += S, j += S;
        propagate(i), propagate(j);

        T res_left = zero, res_right = zero;
        for(; i <= j; i /= 2, j /= 2){
            if((i&1) == 1) res_left = res_left + value[i++];
            if((j&1) == 0) res_right = value[j--] + res_right;
        }
        return res_left + res_right;
    }
};

const int NPRIME = 3;
const int P1 = 1e9+7, P2 = 1e9+9, P3 = 1e9+21;
const int primes[3] = { P1, P2, P3 };

struct mods {
    int vals[NPRIME];

    mods(ll value = 0) {
        for (int i = 0; i < NPRIME; i++)
            vals[i] = value % primes[i];
    }

    #define combine(h, op) \
        mods res; \
        for (int i = 0; i < NPRIME; i++) \
            res.vals[i] = (vals[i] op h.vals[i]) % primes[i]; \
        return res;

    bool operator==(const mods &h) { return !memcmp(this, &h, sizeof(mods)); }
    mods operator*(const mods &h) { combine(h, * 1ll *); }
    mods operator+(const mods &h) { combine(h, +); }

    mods operator*(ll m) { return (*this) * mods(m); }
    mods operator+(ll a) { return (*this) + mods(a); }
};

const int BASE = 1009;
const int MAXL = 1e5 + 100;
mods powers[MAXL], powsum[MAXL];

void init() {
    powers[0] = mods(1);
    powsum[0] = powers[0];

    for(int i=1; i<MAXL; i++) {
        powers[i] = powers[i-1] * BASE;
        powsum[i] = powsum[i-1] + powers[i];
    }
}

struct node {
    int l;
    mods hash;

    node operator+(const node &o) {
        return { l + o.l, hash * powers[o.l] + o.hash };
    }
};

struct update {
    int v;

    node operator()(node &n) {
        if (v == -1) return n;
        return { n.l, powsum[n.l-1] * v };
    }

    update operator+(const update &o) {
        return o;
    }
};

int N, M, K;
string input;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0), cout.precision(15);

    init();

    cin >> N >> M >> K;
    cin >> input;

    seg_tree_lazy<node, update> st(N, {0, 0}, {0, 0}, {-1});

    vector<node> leaves;
    for (char c : input)
        leaves.push_back({1, mods(c)});
    st.set_leaves(leaves);

    for (int q = 0; q < M + K; q++) {
        int t, l, r, v;
        cin >> t >> l >> r >> v;
        l--, r--;

        if (t == 1) {
            st.upd(l, r, { '0' + v });
        } else {
            if (l > r - v) {
                cout << "YES\n";
                continue;
            }

            mods h1 = st.query(l, r - v).hash;
            mods h2 = st.query(l + v, r).hash;

            if (h1 == h2) cout << "YES\n";
            else cout << "NO\n";
        }
    }
}


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

typedef long long ll;

const int NPRIME = 3;
const int P1 = 1e9+7, P2 = 1e9+9, P3 = 1e9+21;
const int primes[3] = { P1, P2, P3 };

struct mods {
    int vals[NPRIME];

    mods(ll value = 0) {
        for (int i = 0; i < NPRIME; i++)
            vals[i] = value % primes[i];
    }

    #define combine(h, op) \
        mods res; \
        for (int i = 0; i < NPRIME; i++) \
            res.vals[i] = (vals[i] op h.vals[i]) % primes[i]; \
        return res;

    bool operator==(const mods &h) { return !memcmp(this, &h, sizeof(mods)); }
    mods operator*(const mods &h) { combine(h, * 1ll *); }
    mods operator+(const mods &h) { combine(h, +); }

    mods operator*(ll m) { return (*this) * mods(m); }
    mods operator+(ll a) { return (*this) + mods(a); }
};

const int BASE = 1009;
const int MAXL = 1e5 + 100;
mods powers[MAXL], powsum[MAXL];

void init() {
    powers[0] = mods(1);
    powsum[0] = powers[0];

    for(int i=1; i<MAXL; i++) {
        powers[i] = powers[i-1] * BASE;
        powsum[i] = powsum[i-1] + powers[i];
    }
}

template<typename T, typename U> struct seg_tree_lazy {
    int S, H;

    T def;
    vector<T> value;

    U noop;
    vector<U> prop;

    void init(int _S) {
        for (S = 1, H = 1; S < _S; ) S *= 2, H++;
        value.resize(2*S, def);
        prop.resize(2*S, noop);
    }

    seg_tree_lazy<T, U>(int _S, T _def = T(), U _noop = U()) {
        def = _def, noop = _noop;
        init(_S);
    }

    seg_tree_lazy<T, U>(vector<T> &leaves, T _def = T(), U _noop = U()) {
        def = _def, noop = _noop;

        init(leaves.size());
        copy(leaves.begin(), leaves.end(), value.begin() + S);

        for (int i = S - 1; i > 0; i--)
            value[i] = value[2 * i] + value[2 * i + 1];
    }

    void apply(int i, U update) {
        value[i] = update(value[i]);
        if(i < S) prop[i] = prop[i] + update;
    }

    void rebuild(int i) {
        for (int l = i/2; l; l /= 2) {
            T combined = value[2*l] + value[2*l+1];
            value[l] = prop[l](combined);
        }
    }

    void propagate(int i) {
        for (int h = H; h > 0; h--) {
            int l = i >> h;
            if (memcmp(&prop[l], &noop, sizeof(U))) {
                apply(2*l, prop[l]);
                apply(2*l+1, prop[l]);
                prop[l] = noop;
            }
        }
    }

    void upd(int i, int j, U update) {
        i += S, j += S;
        propagate(i), propagate(j);

        for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
            if((l&1) == 1) apply(l++, update);
            if((r&1) == 0) apply(r--, update);
        }

        rebuild(i), rebuild(j);
    }

    T query(int i, int j){
        i += S, j += S;
        propagate(i), propagate(j);

        T resl = def, resr = def;
        for(; i <= j; i /= 2, j /= 2){
            if((i&1) == 1) resl = resl + value[i++];
            if((j&1) == 0) resr = value[j--] + resr;
        }
        return resl + resr;
    }
};

struct node {
    int l;
    mods hash;

    node operator+(const node &o) {
        return { l + o.l, hash * powers[o.l] + o.hash };
    }
};

struct update {
    int v;

    node operator()(node &n) {
        if (v == -1) return n;
        return { n.l, powsum[n.l-1] * v };
    }

    update operator+(const update &o) {
        return o;
    }

    bool operator!=(const update &o) {
        return v != o.v;
    }
};

int N, M, K;
string input;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0), cout.precision(15);

    init();

    cin >> N >> M >> K;
    cin >> input;

    vector<node> leaves;
    for (char c : input)
        leaves.push_back({1, mods(c)});

    seg_tree_lazy<node, update> st(leaves, {0, 0}, {-1});

    for (int q = 0; q < M + K; q++) {
        int t, l, r, v;
        cin >> t >> l >> r >> v;

        if (t == 1) {
            st.upd(l - 1, r - 1, { '0' + v });
        } else {
            if (l > r - v) {
                cout << "YES\n";
                continue;
            }

            l--, r--;
            mods h1 = st.query(l, r - v).hash;
            mods h2 = st.query(l + v, r).hash;

            if (h1 == h2) cout << "YES\n";
            else cout << "NO\n";
        }
    }
}


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

typedef long long ll;

const int NPRIME = 2;
const int P1 = 1e9+7, P2 = 1e9+9, P3 = 1e9+21;
const int primes[3] = { P1, P2, P3 };

struct mods {
    ll vals[NPRIME];

    mods(ll value = 0) {
        for (int i = 0; i < NPRIME; i++)
            vals[i] = value % primes[i];
    }

    #define combine(h, op) mods res; for (int i = 0; i < NPRIME; i++) res.vals[i] = (vals[i] op h.vals[i]) % primes[i]; return res;

    bool operator==(const mods &h) { return !memcmp(this, &h, sizeof(mods)); }

    mods operator*(const mods &h) { combine(h, *); }
    mods operator+(const mods &h) { combine(h, +); }

    mods operator*(ll m) { return (*this) * mods(m); }
    mods operator+(ll a) { return (*this) + mods(a); }
};

const int BASE = 1009;
const int MAXL = 1e5 + 100;
mods powers[MAXL], powsum[MAXL];

void init() {
    powers[0] = mods(1);
    powsum[0] = powers[0];

    for(int i=1; i<MAXL; i++) {
        powers[i] = powers[i-1] * BASE;
        powsum[i] = powsum[i-1] + powers[i];
    }
}

template<typename T, typename U> struct seg_tree_lazy {
    int S, H;

    T def;
    vector<T> value;

    U noop;
    vector<U> prop;

    seg_tree_lazy<T, U>(int _S, T _def = T(), U _noop = U()) {
        S = _S, def = _def, noop = _noop;
        assert(__builtin_popcount(S) == 1);
        H = 32 - __builtin_clz(S);

        value.resize(2 * S + 1, def);
        prop.resize(2 * S + 1, noop);
    }

    void apply(int i, U update) {
        value[i] = update(value[i]);
        if(i < S) prop[i] = prop[i] + update;
    }

    void rebuild(int i) {
        for (int l = i/2; l; l /= 2) {
            T combined = value[2*l] + value[2*l+1];
            value[l] = prop[l](combined);
        }
    }

    void propagate(int i) {
        for (int h = H; h > 0; h--) {
            int l = i >> h;
            if (prop[l] != noop) {
                apply(2*l, prop[l]);
                apply(2*l+1, prop[l]);
                prop[l] = noop;
            }
        }
    }

    void upd(int i, int j, U update) {
        i += S, j += S;
        propagate(i), propagate(j);

        for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
            if((l&1) == 1) apply(l++, update);
            if((r&1) == 0) apply(r--, update);
        }

        rebuild(i), rebuild(j);
    }

    T query(int i, int j){
        i += S, j += S;
        propagate(i), propagate(j);

        T resl = def, resr = def;
        for(; i <= j; i /= 2, j /= 2){
            if((i&1) == 1) resl = resl + value[i++];
            if((j&1) == 0) resr = value[j--] + resr;
        }
        return resl + resr;
    }
};

struct node {
    int l;
    mods hash;

    node operator+(const node &o) {
        return { l + o.l, hash * powers[o.l] + o.hash };
    }
};

struct update {
    int v;

    node operator()(node &n) {
        if (v == -1) return n;
        return { n.l, powsum[n.l-1] * v };
    }

    update operator+(const update &o) {
        return o;
    }

    bool operator!=(const update &o) {
        return v != o.v;
    }
};

int N, M, K;
string input;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0), cout.precision(15);

    init();

    cin >> N >> M >> K;
    cin >> input;

    int S = 1; while(S < N) S *= 2;
    seg_tree_lazy<node, update> st(S, {0, 0}, {-1});

    for (int i = 2 * S - 1; i > 0; i--) {
        if(i < S) st.value[i] = st.value[2*i] + st.value[2*i+1];
        else if(i < S + N) st.value[i] = {1, mods(input[i-S])};
        else st.value[i] = {1, mods(0)};
    }

    for (int q = 0; q < M + K; q++) {
        int t, l, r, v;
        cin >> t >> l >> r >> v;

        if (t == 1) {
            st.upd(l - 1, r - 1, { '0' + v });
        } else {
            if (l > r - v) {
                cout << "YES\n";
                continue;
            }

            l--, r--;
            mods h1 = st.query(l, r - v).hash;
            mods h2 = st.query(l + v, r).hash;

            if (h1 == h2) cout << "YES\n";
            else cout << "NO\n";
        }
    }
}