#include<bits/stdc++.h>
#define cint const int&
#define cstr const auto*const
using namespace std;
const int maxn = 1e5 + 1, lim = 30;
int l1, l2, r1, r2, a[maxn], sa[maxn], rk[maxn], tp[maxn << 1], bn[maxn], hzr[maxn], n, m;
char s[maxn];
inline void getsa(cstr s, cint n) {
int m = max(n, 255);
memset(bn + 1, 0, sizeof(bn[0]) * m);
for (int i = 1; i <= n; ++i) ++bn[rk[i] = s[i]];
for (int i = 2; i <= m; ++i) bn[i] += bn[i - 1];
for (int i = n; i > 0; --i) sa[bn[rk[i]]--] = i;
for (int j = 1, cnt = 0; j <= n; j <<= 1, cnt = 0) {
for (int i = n - j + 1; i <= n; ++i) tp[++cnt] = i;
for (int i = 1; i <= n; ++i)
if (sa[i] - j > 0) tp[++cnt] = sa[i] - j;
memset(bn + 1, 0, sizeof(bn[0]) * m);
for (int i = 1; i <= n; ++i) ++bn[rk[i]];
for (int i = 2; i <= m; ++i) bn[i] += bn[i - 1];
for (int i = n; i > 0; --i) sa[bn[rk[tp[i]]]--] = tp[i];
memcpy(tp + 1, rk + 1, sizeof(tp[0]) * n);
rk[sa[1]] = cnt = 1;
for (int i = 2; i <= n; ++i)
rk[sa[i]] = (tp[sa[i]] != tp[sa[i - 1]]) || (tp[sa[i] + j] != tp[sa[i - 1] + j]) ? ++cnt : cnt;
if ((m = cnt) == n) break;
}
}
inline void gethzr(cstr s, cint n) {
for (int i = 1, k = 0; i <= n; ++i) {
if (rk[i] == 1) continue;
if (k) --k;
int j = sa[rk[i] - 1];
while (j + k <= n && i + k <= n && s[i + k] == s[j + k]) ++k;
hzr[rk[i]] = k;
}
}
int minval[lim][maxn];
inline void init(cint n) {
for (int i = 1; i < lim; ++i)
for (int j = 1; j + (1 << (i - 1)) <= n; ++j)
minval[i][j] = min(minval[i - 1][j], minval[i - 1][j + (1 << (i - 1))]);
}
inline int getmin(cint l, cint r) {
int lg = (8 * sizeof(r - l + 1) - 1) - __builtin_clz(r - l + 1);
return min(minval[lg][l], minval[lg][r - (1 << lg) + 1]);
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m >> s + 1;
getsa(s, n), gethzr(s, n);
memcpy(minval[0], hzr, sizeof(hzr[0]) * (n + 1)), init(n);
while (m--) {
cin >> l1 >> r1 >> l2 >> r2;
if (rk[l1] > rk[l2]) swap(l1, l2), swap(r1, r2);
if (r1 - l1 == r2 - l2 && (l1 == l2 || getmin(rk[l1] + 1, rk[l2]) > r1 - l1))
cout << "Yes\n";
else cout << "No\n";
}
}