#include <bits/stdc++.h>
#define debug(x) (cout << #x << " " << x << "\n")
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int N = 1e6 + 5, base = 1e9 + 7;
int n, q;
ull tree[N << 2], pw[N], tree2[N << 2], hs[N];
string s, t;
void pushup(int cur, int l, int r) {
int mid = l + r >> 1;
tree[cur] = tree[cur << 1] * pw[r - mid] + tree[cur << 1 | 1];
tree2[cur] = tree2[cur << 1] * pw[r - mid] + tree2[cur << 1 | 1];
}
void build(int cur, int l, int r) {
if (l == r) { tree[cur] = s[l], tree2[cur] = t[l]; return ; }
int mid = l + r >> 1;
build(cur << 1, l, mid);
build(cur << 1 | 1, mid + 1, r);
pushup(cur, l, r);
}
void update(int cur, int l, int r, int x, char ch) {
if (l > x || r < x) return ;
if (l == r && l == x) { tree[cur] = s[l] = ch; return ; }
int mid = l + r >> 1;
update(cur << 1, l, mid, x, ch);
update(cur << 1 | 1, mid + 1, r, x, ch);
pushup(cur, l, r);
}
void update2(int cur, int l, int r, int x, char ch) {
if (l > x || r < x) return ;
if (l == r && l == x) { tree2[cur] = t[l] = ch; return ; }
int mid = l + r >> 1;
update(cur << 1, l, mid, x, ch);
update(cur << 1 | 1, mid + 1, r, x, ch);
pushup(cur, l, r);
}
ull query(int cur, int l, int r, int qx, bool f) {
if (l > qx) return 0;
if (r <= qx) return f ? tree2[cur] : tree[cur];
int mid = l + r >> 1;
return query(cur << 1, l, mid, qx, f) * pw[r - mid] + query(cur << 1 | 1, mid + 1, r, qx, f);
}
ull get_hs(int l, int r, bool f) {
return query(1, 1, n, r, f) - query(1, 1, n, l - 1, f) * pw[r - l + 1];
}
int main() {
srand(time(0));
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> q >> s;
t = s, reverse(t.begin(), t.end()), t = '#' + t;
s = '#' + s;
pw[0] = 1;
for (int i = 1; i <= n; i++) pw[i] = pw[i - 1] * base;
build(1, 1, n);
while (q --) {
int opt; cin >> opt;
if (opt == 1) {
int x; char c; cin >> x >> c;
update(1, 1, n, x, c);
update2(1, 1, n, n - x + 1, c);
} else {
int l, r; cin >> l >> r;
cout << (get_hs(l, r, 0) == get_hs(n - r + 1, n - l + 1, 1) ? "Yes\n" : "No\n");
}
}
return 0;
}