#include <bits/stdc++.h>
using namespace std;
class SegmentTree {
 public:
  SegmentTree(int _n) : n(_n), N(_n << 1), data(N, INT_MAX) {
    h = 0;
    while (1 << h <= N) {
      ++h;
    }
  }
  void build(vector<int>& nums) {
    copy(nums.begin(), nums.end(), data.begin() + n);
    for (int i = n - 1; i > 0; --i) {
      data[i] = min(data[i << 1], data[i << 1 | 1]);
    }
  }
  int get(int l, int r) {
    l += n;
    r += n;
    int res = INT_MAX;
    while (l <= r) {
      if (l & 0x1) {
        res = min(res, data[l++]);
      }
      if (!(r & 0x1)) {
        res = min(res, data[r--]);
      }
      l >>= 1;
      r >>= 1;
    }
    return res;
  }

 private:
  int N;
  int n;
  int h;
  vector<int> data;
};
class SuffixArray {
 public:
  SuffixArray(const string& s) : N(s.length()), st(N + 100) { build(s); }
  const vector<int>& getSuffixArray() { return sa; }
  const vector<int>& getIndexArray() { return indices; }
  const vector<int>& getLcpArray() { return lcp; }
  long long lcpOf(int l, int r) {
    if (l == r) {
      return N - l;
    }
    l = indices[l];
    r = indices[r];
    if (l > r) {
      swap(l, r);
    }
    return st.get(l + 1, r);
  }

 private:
  int N;
  vector<int> sa;
  vector<int> indices;
  vector<int> lcp;
  SegmentTree st;
  struct Datum {
   public:
    Datum(int i = -1, int k0 = -1, int k1 = -1)
        : index(i), key0(k0), key1(k1) {}
    bool operator<(const Datum& other) const {
      return key0 == other.key0 ? key1 < other.key1 : key0 < other.key0;
    }
    int index;
    int key0;
    int key1;
  };
  void build(const string& s) {
    N = s.length();
    sa.clear();
    sa.resize(N, -1);
    indices.clear();
    indices.resize(N, -1);
    vector<Datum> data(N);
    for (int i = 0; i < N; ++i) {
      data[i].index = i;
      data[i].key0 = s[i];
    }
    auto update = [&](int gap) {
      int idx = -1, preKey0 = -1, preKey1 = -1;
      for (int i = 0; i < N; ++i) {
        int key0 = data[i].key0, key1 = data[i].key1;
        if (key0 != preKey0 || key1 != preKey1) {
          data[i].key0 = ++idx;
          preKey0 = key0;
          preKey1 = key1;
        } else {
          data[i].key0 = idx;
        }
        indices[data[i].index] = i;
      }
      for (int i = 0; i < N; ++i) {
        int j = data[i].index + gap;
        if (j < N) {
          data[i].key1 = data[indices[j]].key0;
        } else {
          data[i].key1 = -1;
        }
      }
    };
    sort(data.begin(), data.end());
    int gap = 1;
    update(gap);
    while (gap <= N) {
      sort(data.begin(), data.end());
      update(gap <<= 1);
    }
    for (int i = 0; i < N; ++i) {
      sa[i] = data[i].index;
      indices[sa[i]] = i;
    }
    buildLcp(s);
  }
  void buildLcp(const string& s) {
    lcp.clear();
    lcp.resize(N, 0);
    int len = 0;
    for (int i = 0; i < N; ++i) {
      int idx = indices[i];
      if (idx == 0) {
        lcp[idx] = 0;
        len = 0;
        continue;
      }
      int j = sa[idx - 1];
      while (i + len < N && j + len < N && s[i + len] == s[j + len]) {
        ++len;
      }
      lcp[idx] = len;
      if (len > 0) {
        --len;
      }
    }
    st.build(lcp);
  }
};
class Solution {
 public:
  Solution(const string& s)
      : N(s.length()),
        sfxArr(s),
        lcp(N + 1000, make_pair(-1, -1)),
        cnts(N + 1000, 0),
        sums(N + 1000, 0LL),
        S(s) {}
  long long query(vector<int>& A, int n, vector<int>& B, int m) {
    const auto& indices = sfxArr.getIndexArray();
    auto cmp = [&](int l, int r) { return indices[l] < indices[r]; };
    sort(A.begin(), A.begin() + n, cmp);
    sort(B.begin(), B.begin() + m, cmp);
    if (n > m) {
      swap(A, B);
      swap(n, m);
    }
    long long res = 0;
    int size = 0;
    long long sum = 0;
    for (int i = 0, j = 0; i < n || j < m;) {
      if (j == m) {
        break;
      }
      if (i < n && indices[A[i]] <= indices[B[j]]) {
        int len = 0;
        int cnt = 0;
        if (i == 0) {
          len = N - A[i];
          cnt = 0;
        } else {
          len = sfxArr.lcpOf(A[i - 1], A[i]);
          cnt = 0;
          while (size > 0) {
            if (lcp[size - 1].first >= len) {
              sum -= 1LL * lcp[size - 1].first * lcp[size - 1].second;
              cnt += lcp[size - 1].second;
              --size;
            } else {
              break;
            }
          }
        }
        if (cnt > 0) {
          lcp[size].first = len;
          lcp[size].second = cnt;
          sum += 1LL * len * cnt;
          cnts[size + 1] = cnts[size] + cnt;
          sums[size + 1] = sum;
          ++size;
        }
        lcp[size].first = N - A[i];
        lcp[size].second = 1;
        sum += N - A[i];
        cnts[size + 1] = cnts[size] + 1;
        sums[size + 1] = sum;
        assert(cnts[size + 1] == i + 1);
        ++size;
        ++i;
      } else {
        if (i - 1 >= 0) {
          int len = sfxArr.lcpOf(A[i - 1], B[j]);
          auto it =
              lower_bound(lcp.begin(), lcp.begin() + size, make_pair(len, 0));
          int idx = it - lcp.begin() - 1;
          if (idx < 0) {
            res += 1LL * len * i;
          } else {
            res += sums[idx + 1] + 1LL * len * (i - cnts[idx + 1]);
          }
        }
        ++j;
      }
    }
    size = 0;
    sum = 0;
    for (int i = n - 1, j = m - 1; i >= 0 || j >= 0;) {
      if (j < 0) {
        break;
      }
      if (i >= 0 && indices[A[i]] > indices[B[j]]) {
        int len = 0;
        int cnt = 0;
        if (i == n - 1) {
          len = N - A[i];
          cnt = 0;
        } else {
          len = sfxArr.lcpOf(A[i + 1], A[i]);
          cnt = 0;
          while (size > 0) {
            if (lcp[size - 1].first >= len) {
              sum -= 1LL * lcp[size - 1].first * lcp[size - 1].second;
              cnt += lcp[size - 1].second;
              --size;
            } else {
              break;
            }
          }
        }
        if (cnt > 0) {
          lcp[size].first = len;
          lcp[size].second = cnt;
          sum += 1LL * len * cnt;
          cnts[size + 1] = cnts[size] + cnt;
          sums[size + 1] = sum;
          ++size;
        }
        lcp[size].first = N - A[i];
        lcp[size].second = 1;
        sum += N - A[i];
        cnts[size + 1] = cnts[size] + 1;
        sums[size + 1] = sum;
        assert(cnts[size + 1] == n - i);
        ++size;
        --i;
      } else {
        if (i + 1 < n) {
          int len = sfxArr.lcpOf(A[i + 1], B[j]);
          auto it =
              lower_bound(lcp.begin(), lcp.begin() + size, make_pair(len, 0));
          int idx = it - lcp.begin() - 1;
          if (idx < 0) {
            res += 1LL * len * (n - i - 1);
          } else {
            res += sums[idx + 1] + 1LL * len * (n - i - 1 - cnts[idx + 1]);
          }
        }
        --j;
      }
    }
    return res;
  }

 private:
  int N;
  string S;
  SuffixArray sfxArr;
  vector<pair<int, int>> lcp;
  vector<int> cnts;
  vector<long long> sums;
  void check(vector<int>& A, int n, vector<int>& B, int m, long long res) {
    long long ans = 0;
    int N = S.length();
    auto LCP = [&](int x, int y) {
      int res = 0;
      for (int i = x, j = y; i < N && j < N; ++i, ++j) {
        if (S[i] == S[j]) {
          ++res;
        } else {
          break;
        }
      }
      return res;
    };
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < m; ++j) {
        int a = A[i], b = B[j];
        ans += LCP(a, b);
      }
    }
    if (ans != res) {
      cout << "ERROR: WA "
           << " got " << res << " but expected " << ans << endl;
    }
  }
};
void test() {
  vector<string> ts = {{"adsfadfqiewruypzdjfquwieroyzsdf",
                        "zduoifyqewrjhlzjkdhfvuioqerwy",
                        "adsfuiaednbklzjdrfyquioerwyhadnfb", "aaaaaaaaaaaaaaa",
                        "axaaxadaxaacaaxxaad"}};
  cout << "test " << endl;
  for (auto s : ts) {
    Solution sol(s);
    int n = s.length();
    vector<int> A(n);
    iota(A.begin(), A.end(), 0);
    vector<int> B(n);
    iota(B.begin(), B.end(), 0);
    sol.query(A, n, B, n);
  }
}
int main(int argc, char** argv) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, q;
  cin >> n >> q;
  string s;
  cin >> s;
  Solution sol(s);
  vector<int> A(n + 100);
  vector<int> B(n + 100);
  int k, l;
  while (q-- > 0) {
    cin >> k >> l;
    for (int i = 0; i < k; ++i) {
      cin >> A[i];
      --A[i];
    }
    for (int j = 0; j < l; ++j) {
      cin >> B[j];
      --B[j];
    }
    cout << sol.query(A, k, B, l) << endl;
  }
  return 0;
}
