#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
template <class c>
struct rge {
  c b, e;
};
template <class c>
rge<c> range(c i, c j) {
  return rge<c>{i, j};
}
template <class c>
auto dud(c* x) -> decltype(cerr << *x, 0);
template <class c>
char dud(...);
struct debug {
  template <class c>
  debug& operator<<(const c&) {
    return *this;
  }
};
const int nax = 3e5 + 5;
int par[nax];
vector<int> children[nax];
char ch[nax];
int in[nax], out[nax];
int depth[nax];
pair<int, int> nxt_par[nax];
int T = 0;
int has[nax][26][2];
int total[nax];
struct Node {
  int big, lazy;
  void add(int x) {
    big += x;
    lazy += x;
  }
};
int B = 1;
struct Tree {
  vector<Node> tree;
  void rec(int id, int low, int high, int q_low, int q_high, int diff) {
    if (high < q_low || q_high < low) {
      return;
    }
    if (q_low <= low && high <= q_high) {
      tree[id].add(diff);
      return;
    }
    for (int b : {2 * id, 2 * id + 1}) {
      tree[b].add(tree[id].lazy);
    }
    tree[id].lazy = 0;
    int last_left = (low + high) / 2;
    rec(2 * id, low, last_left, q_low, q_high, diff);
    rec(2 * id + 1, last_left + 1, high, q_low, q_high, diff);
    tree[id].big = max(tree[2 * id].big, tree[2 * id + 1].big);
  }
} trees[26];
void dfs(int a) {
  in[a] = ++T;
  for (int b : children[a]) {
    depth[b] = depth[a] + 1;
    dfs(b);
  }
  out[a] = T;
}
int bad;
void add(int i, int A, int diff) {
  debug();
  debug() << "add"
             " ["
          << "i"
             ": "
          << (i)
          << "] "
             " ["
          << "A"
             ": "
          << (A)
          << "] "
             " ["
          << "diff"
             ": "
          << (diff) << "] ";
  trees[A].rec(1, 0, B - 1, in[i], out[i], diff);
  for (pair<int, int> x = nxt_par[i]; x.first; x = nxt_par[x.first]) {
    debug() << "> "
               " ["
            << "x"
               ": "
            << (x) << "] ";
    if (total[x.first] < 0) {
      --bad;
    }
    int Z = max(has[x.first][A][0], has[x.first][A][1]);
    total[x.first] += Z;
    has[x.first][A][x.second] += diff;
    int Y = max(has[x.first][A][0], has[x.first][A][1]);
    total[x.first] -= Y;
    if (total[x.first] < 0) {
      ++bad;
    }
    if (total[x.first] < 0) {
      debug() << ">>> "
                 " ["
              << "x"
                 ": "
              << (x)
              << "] "
                 " ["
              << "has[x.first][A][0]"
                 ": "
              << (has[x.first][A][0])
              << "] "
                 " ["
              << "has[x.first][A][1]"
                 ": "
              << (has[x.first][A][1])
              << "] "
                 " ["
              << "total[x.first]"
                 ": "
              << (total[x.first]) << "] ";
      debug() << ">>>2 "
                 " ["
              << "has[x.first][3][0]"
                 ": "
              << (has[x.first][3][0])
              << "] "
                 " ["
              << "has[x.first][3][1]"
                 ": "
              << (has[x.first][3][1]) << "] ";
    }
    if (Z == Y) {
      break;
    }
  }
}
int main() {
  int n, q;
  scanf("%d%d", &n, &q);
  for (int i = 2; i <= n; ++i) {
    scanf("%d %c", &par[i], &ch[i]);
    children[par[i]].push_back(i);
  }
  for (int i = 2; i <= n; ++i) {
    int p = par[i];
    if ((int)children[p].size() >= 2) {
      int which = -1;
      if (children[p][0] == i) {
        which = 0;
      } else if (children[p][1] == i) {
        which = 1;
      } else {
        assert(false);
      }
      nxt_par[i] = make_pair(p, which);
    } else {
      nxt_par[i] = nxt_par[p];
    }
  }
  dfs(1);
  int should = -1;
  for (int i = 2; i <= n; ++i) {
    if (children[i].empty()) {
      if (should == -1) {
        should = depth[i];
        continue;
      }
      if (should != depth[i]) {
        debug() << "spec";
        while (q--) {
          puts("Fou");
        }
        return 0;
      }
    }
  }
  assert(should != -1);
  while (B <= n) {
    B *= 2;
  }
  for (int i = 0; i < 26; ++i) {
    trees[i].tree.resize(2 * B, Node{0, 0});
  }
  for (int i = 1; i <= n; ++i) {
    total[i] = should - depth[i];
  }
  for (int i = 2; i <= n; ++i) {
    if (ch[i] != '?') {
      int A = ch[i] - 'a';
      add(i, A, 1);
    }
  }
  debug();
  debug() << " ["
          << "bad"
             ": "
          << (bad) << "] ";
  while (q--) {
    int i;
    char letter;
    scanf("%d %c", &i, &letter);
    if (ch[i] != '?') {
      int A = ch[i] - 'a';
      add(i, A, -1);
    }
    ch[i] = letter;
    if (ch[i] != '?') {
      int A = ch[i] - 'a';
      add(i, A, 1);
    }
    vector<int> info(26);
    int suma = 0;
    for (int j = 0; j < 26; ++j) {
      info[j] = trees[j].tree[1].big;
      suma += info[j];
    }
    debug() << " ["
            << "suma"
               ": "
            << (suma)
            << "] "
               " ["
            << "should"
               ": "
            << (should)
            << "] "
               " ["
            << "bad"
               ": "
            << (bad) << "] ";
    if (suma > should || bad > 0) {
      puts("Fou");
    } else {
      long long answer = 0;
      for (int j = 0; j < 26; ++j) {
        answer += (long long)(j + 1) * (info[j] + should - suma);
      }
      printf("Shi %lld\n", answer);
    }
  }
}
