#include <bits/stdc++.h>
using namespace std;
template <class T>
struct SegmentTree {
  T (*merge)(int, int, int, T, T);
  int n;
  vector<T> ST;
  void build(int i, int l, int r, vector<T> &values) {
    if (l == r) {
      ST[i] = values[l];
      return;
    }
    build(i << 1, l, (l + r) >> 1, values);
    build(i << 1 | 1, (l + r) / 2 + 1, r, values);
    ST[i] = merge(l, (l + r) >> 1, r, ST[i << 1], ST[i << 1 | 1]);
  }
  SegmentTree(vector<T> &values, T (*merge)(int l1, int l2, int l3, T a, T b))
      : merge(merge) {
    n = values.size();
    ST.resize(n << 2 | 3);
    build(1, 0, n - 1, values);
  }
  void update(int i, int l, int r, int pos, T val) {
    if (r < pos or l > pos) return;
    if (l == r) {
      ST[i] = val;
      return;
    }
    update(i << 1, l, (l + r) >> 1, pos, val);
    update(i << 1 | 1, (l + r) / 2 + 1, r, pos, val);
    ST[i] = merge(l, (l + r) >> 1, r, ST[i << 1], ST[i << 1 | 1]);
  }
  void update(int pos, T val) { update(1, 0, n - 1, pos, val); }
  T query(int i, int l, int r, int a, int b) {
    if (l >= a and r <= b) return ST[i];
    int mid = (l + r) >> 1;
    if (mid < a) return query(i << 1 | 1, mid + 1, r, a, b);
    if (mid >= b) return query(i << 1, l, mid, a, b);
    return merge(max(a, l), mid, min(r, b), query(i << 1, l, mid, a, b),
                 query(i << 1 | 1, mid + 1, r, a, b));
  }
  T query(int a, int b) {
    if (a > b)
      return merge(a, n - 1, b, query(1, 0, n - 1, 0, b),
                   query(1, 0, n - 1, a, n - 1));
    return query(1, 0, n - 1, a, b);
  }
};
int f(int a, int b, int c, int A, int B) { return A ^ B; }
int c;
vector<int> L, R;
vector<vector<int> > nodes_in_depth;
void dfs(int node, vector<int> &parent, vector<vector<int> > &children,
         vector<int> &depth, vector<int> &vec, string &S) {
  L[node] = c;
  vec[c] = (1 << (S[node] - 'a'));
  for (int node2 : children[node]) {
    depth[node2] = depth[node] + 1;
    nodes_in_depth[depth[node] + 1].push_back(node2);
    c++;
    dfs(node2, parent, children, depth, vec, S);
  }
  R[node] = c;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  c = 0;
  cin >> n >> m;
  vector<int> parent(n), depth(n, -1), vec(n), empt(n, (1 << 30));
  L.resize(n);
  R.resize(n);
  nodes_in_depth.resize(n + 1);
  vector<vector<int> > children(n);
  for (int i = 1; i < n; i++) {
    cin >> parent[i];
    parent[i]--;
    children[parent[i]].push_back(i);
  }
  string S;
  cin >> S;
  depth[0] = 1;
  nodes_in_depth[1].push_back(1);
  dfs(0, parent, children, depth, vec, S);
  SegmentTree<int> ST(empt, f);
  vector<pair<int, pair<int, int> > > q(m);
  vector<bool> oka(m, false);
  for (int i = 0; i < m; i++) {
    int v, h;
    cin >> v >> h;
    q[i] = make_pair(h, make_pair(v - 1, i));
  }
  sort(q.begin(), q.end());
  reverse(q.begin(), q.end());
  int curr_depth = 0;
  for (int i = 0; i < m; i++) {
    int h = q[i].first;
    int v = q[i].second.first;
    int pos = q[i].second.second;
    if (curr_depth != h) {
      for (int node : nodes_in_depth[curr_depth]) {
        ST.update(L[node], (1 << 30));
      }
      for (int node : nodes_in_depth[h]) {
        ST.update(L[node], vec[L[node]]);
      }
      curr_depth = h;
    }
    int thing = ST.query(L[v], R[v]);
    int imp = 0;
    for (int i = 0; i < 30; i++) {
      if ((1 << i) & thing) imp++;
    }
    oka[pos] = (imp <= 1);
  }
  for (int i = 0; i < m; i++) {
    if (oka[i])
      cout << "Yes\n";
    else
      cout << "No\n";
  }
  return 0;
}
