#include <bits/stdc++.
h>
#define task "BriantheCrab"
#define int long long
#define pii pair <int, int>
#define fi first
#define se second
#define szf sizeof
#define sz(s) (int)((s).size())
using namespace std;
template <class T> void mini (T &t, T f) {if (t > f) t = f;}
template <class T> void maxi (T &t, T f) {if (t < f) t = f;}
const int maxN = 1e5 + 5;
const int inf = 1e18 + 7;
const int mod = 1e9 + 7;
const int INF_V = 2e9;
int gn;
int va[maxN];
long long pw[30];
int a[maxN];
long long blk_s[maxN]; // Sqrt Decomposition: block_sum_p
int blk_m[maxN]; // Sqrt Decomposition: block_min_v
int blk_sz; // Block size
int num_blks; // Number of blocks
void build_sqrt() {
if (gn == 0) {
blk_sz = 1;
num_blks = 0;
return;
}
blk_sz = sqrt(gn);
if (blk_sz == 0) blk_sz = 1;
num_blks = (gn + blk_sz - 1) / blk_sz;
for (int i = 0; i < num_blks; ++ i ) {
blk_s[i] = 0;
blk_m[i] = INF_V;
}
for (int i = 1; i <= gn; ++ i ) {
int b_idx = (i - 1) / blk_sz;
blk_s[b_idx] += pw[va[i]];
mini(blk_m[b_idx], va[i]);
}
}
void upd_sqrt(int p, int nval) {
int b_idx = (p - 1) / blk_sz;
int oval = va[p];
if (oval == nval) return;
va[p] = nval;
blk_s[b_idx] -= pw[oval];
blk_s[b_idx] += pw[nval];
if (nval < blk_m[b_idx]) {
blk_m[b_idx] = nval;
} else if (oval == blk_m[b_idx]) {
blk_m[b_idx] = INF_V;
int L_blk = b_idx * blk_sz + 1;
int R_blk = min((b_idx + 1) * blk_sz, gn);
for (int i = L_blk; i <= R_blk; ++ i ) {
mini(blk_m[b_idx], va[i]);
}
}
}
pair<long long, int> qry_sqrt(int qL, int qR) {
if (qL > qR) return {0, INF_V};
long long cur_s = 0;
int cur_m = INF_V;
int i = qL;
while (i <= qR) {
int b_idx = (i - 1) / blk_sz;
int L_blk = b_idx * blk_sz + 1; // Start of current block
int R_blk = min((b_idx + 1) * blk_sz, gn); // End of current block
if (i == L_blk && R_blk <= qR) {
cur_s += blk_s[b_idx];
mini(cur_m, blk_m[b_idx]);
i = R_blk + 1;
} else {
cur_s += pw[va[i]];
mini(cur_m, va[i]);
++ i;
}
}
return {cur_s, cur_m};
}
void solve () {
int Q, X;
cin >> gn >> Q >> X;
pw[0] = 1;
for (int i = 1; i <= 26; ++ i ) {
pw[i] = pw[i-1] * 2;
}
string s_str;
cin >> s_str;
for (int i = 1; i <= gn; ++ i ) {
va[i] = s_str[i-1] - 'a';
}
build_sqrt();
for (int qi = 0; qi < Q; ++ qi ) {
char type;
cin >> type;
if (type == '!') {
int p_idx;
char ch;
cin >> p_idx >> ch;
int nval = ch - 'a';
upd_sqrt(p_idx, nval);
} else {
int qL, qR;
long long TQ;
cin >> qL >> qR >> TQ;
int len = qR - qL + 1;
if (len == 1) {
long long PL = pw[va[qL]];
if (TQ == PL) {
cout << "YES\n";
} else {
cout << "NO\n";
}
} else {
long long PR = pw[va[qR]];
long long PRm1 = pw[va[qR-1]];
if (len == 2) {
if (TQ == (PR - PRm1)) {
cout << "YES\n";
} else {
cout << "NO\n";
}
} else {
long long targetT = TQ + PRm1 - PR;
pair<long long, int> res_W = qry_sqrt(qL, qR - 2);
long long sumW = res_W.fi;
int minV = res_W.se;
// For len >= 3, the range [qL, qR-2] is non-empty, so minV
should be valid.
// And pw[minV] will be >= 1.
long long gW = pw[minV];
if (targetT % gW != 0) {
cout << "NO\n";
} else {
long long sumWg = sumW / gW;
long long targetTg = targetT / gW;
if (abs(targetTg) > sumWg || (sumWg - targetTg) % 2 != 0) {
cout << "NO\n";
} else {
cout << "YES\n";
}
}
}
}
}
}
}
signed main () {
cin.tie (nullptr) -> sync_with_stdio (false);
if (fopen (task".inp", "r")) {
freopen (task".inp", "r", stdin);
freopen (task".out", "w", stdout);
}
int t = 1;
//cin >> t;
while (t --) {
solve ();
}
return 0;
}