#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
inline int read() {
int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}
const int N = 200005;
int ls[N * 20], rs[N * 20], Root[N], pos[N], ch[N][26], len[N], fa[N], tmp[N], xl[N], f[N][20];
int TreeIndex, Index = 1, Last = 1, n;
char s[N];
void Insert(int l,int r,int &now,int p) {
now = ++TreeIndex;
if (l == r) return ;
int mid = (l + r) >> 1;
if (p <= mid) Insert(l, mid, ls[now], p);
else Insert(mid + 1, r, rs[now], p);
}
int query(int l,int r,int now,int L,int R) {
if (!now) return 0;
if (L <= l && r <= R) return 1;
int mid = (l + r) >> 1;
if (L <= mid && query(l, mid, ls[now], L, R)) return 1;
if (R > mid && query(mid + 1, r, rs[now], L, R)) return 1;
return 0;
}
int Merge(int x,int y) {
if (!x || !y) return x + y;
int z = ++TreeIndex;
ls[z] = Merge(ls[x], ls[y]);
rs[z] = Merge(rs[x], rs[y]);
return z;
}
void extend(int c,int i) {
int np = ++Index, p = Last; pos[i] = np; // pos[i] = np; !!!!!
len[np] = len[p] + 1;
for (; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
if (!p) fa[np] = 1;
else {
int q = ch[p][c];
if (len[q] == len[p] + 1) fa[np] = q;
else {
int nq = ++Index;
memcpy(ch[nq], ch[q], sizeof(ch[q]));
fa[nq] = fa[q];
fa[np] = fa[q] = nq;
len[nq] = len[p] + 1;
for (; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
}
}
Last = np;
Insert(1, n, Root[np], i);
}
bool check(int mid,int x,int l,int r) {
for (int i = 19; ~i; --i) if (len[f[x][i]] >= mid) x = f[x][i];
return query(1, n, Root[x], l, r);
}
int main() {
n = read();int m = read();
scanf("%s", s + 1);
reverse(s + 1, s + n + 1);
for (int i = 1; i <= n; ++i) extend(s[i] - 'a', i);
for (int i = 1; i <= Index; ++i) tmp[len[i]] ++;
for (int i = 1; i <= n; ++i) tmp[i] += tmp[i - 1];
for (int i = Index; i >= 1; --i) xl[tmp[len[i]]--] = i;
for (int i = Index; i > 1; --i) {
int x = xl[i];
Root[fa[x]] = Merge(Root[fa[x]], Root[x]);
}
for (int i = 1; i <= Index; ++i) f[i][0] = fa[i];
for (int j = 1; j <= 19; ++j)
for (int i = 1; i <= Index; ++i) f[i][j] = f[f[i][j - 1]][j - 1];
while (m --) {
int a = n - read() + 1, b = n - read() + 1, c = n - read() + 1, d = n - read() + 1;
swap(a, b); swap(c, d);
int l = 1, r = min(d - c + 1, b - a + 1), ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid, pos[d], a + mid - 1, b)) ans = mid, l = mid + 1;
else r = mid - 1;
}
printf("%d\n", ans);
}
return 0;
}