#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 7;
const int ALPHA = 26;
int p[MAXN];
char c[MAXN];
int mp[MAXN];
int lvl[MAXN];
int parent[MAXN];
int niche[MAXN];
vector<int> edg[MAXN];
vector<int> adj[MAXN];
vector<int> info[MAXN];
vector<int> query[MAXN];
vector<int> tmp[MAXN];
int getIdx(char c) {
  if (c == '?') return ALPHA;
  return c - 'a';
}
void dfs(int u) {
  info[u].resize(ALPHA + 1);
  query[u].resize(ALPHA + 1);
  tmp[u].resize(ALPHA + 1);
  for (int v : edg[u]) {
    lvl[v] = lvl[u] + 1;
    dfs(v);
    niche[u] = 1 + niche[v];
    if (c[v] != '?') {
      info[mp[v]][getIdx(c[v])]++;
      info[mp[v]][ALPHA]++;
    }
    if (u == 1 || edg[u].size() == 2) {
      adj[u].push_back(mp[v]);
    }
  }
  if (edg[u].size() != 1)
    mp[u] = u;
  else
    mp[u] = mp[edg[u][0]];
}
int cntInvalid;
bool flag[MAXN];
void calculate(int u) {
  cntInvalid -= flag[u];
  flag[u] = false;
  for (int v : adj[u]) {
    if (flag[v]) {
      flag[u] = true;
    }
    tmp[v] = query[v];
    for (int i = 0; i <= ALPHA; i++) tmp[v][i] += info[v][i];
  }
  query[u] = tmp[adj[u][0]];
  if (adj[u].size() == 2) {
    int v = adj[u][1];
    query[u][ALPHA] = 0;
    for (int i = 0; i < ALPHA; i++) {
      query[u][i] = max(query[u][i], tmp[v][i]);
      query[u][ALPHA] += query[u][i];
    }
    if (query[u][ALPHA] > niche[u]) {
      flag[u] = true;
    }
  }
  if (flag[u]) {
    cntInvalid++;
  }
}
void recalculate(int u, int from, int to) {
  cntInvalid -= flag[u];
  flag[u] = false;
  int mxfrom = 0, mxto = 0;
  for (int v : adj[u]) {
    if (flag[v]) {
      flag[u] = true;
    }
    mxfrom = max(mxfrom, query[v][from] + info[v][from]);
    mxto = max(mxto, query[v][to] + info[v][to]);
  }
  if (from != ALPHA) {
    query[u][ALPHA] -= query[u][from];
    query[u][from] = mxfrom;
    query[u][ALPHA] += query[u][from];
  }
  if (to != ALPHA) {
    query[u][ALPHA] -= query[u][to];
    query[u][to] = mxto;
    query[u][ALPHA] += query[u][to];
  }
  if (query[u][ALPHA] > niche[u]) {
    flag[u] = true;
  }
  if (flag[u]) {
    cntInvalid++;
  }
}
void solve(int u) {
  fill(query[u].begin(), query[u].end(), 0);
  if (adj[u].empty()) return;
  for (int v : adj[u]) {
    parent[v] = u;
    solve(v);
  }
  calculate(u);
}
void update(int u, int from, int to) {
  while (u > 1) {
    u = parent[u];
    recalculate(u, from, to);
  }
}
int score() {
  int ans = 351 * (niche[1] - query[1][ALPHA]);
  for (int i = 0; i < ALPHA; i++) {
    ans += (i + 1) * query[1][i];
  }
  return ans;
}
void ask() {
  if (cntInvalid > 0)
    cout << "Fou\n";
  else
    cout << "Shi " << score() << "\n";
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, q;
  cin >> n >> q;
  for (int i = 2; i <= n; i++) {
    cin >> p[i] >> c[i];
    edg[p[i]].push_back(i);
  }
  dfs(1);
  bool alwaysFou = false;
  int level = 0;
  for (int i = 2; i <= n; i++) {
    if (edg[i].empty()) {
      if (level > 0 && level != lvl[i]) {
        alwaysFou = true;
        break;
      }
      level = lvl[i];
    }
  }
  solve(1);
  while (q--) {
    int _v;
    char _c;
    cin >> _v >> _c;
    if (alwaysFou) {
      cout << "Fou\n";
      continue;
    }
    if (c[_v] != '?') {
      info[mp[_v]][getIdx(c[_v])]--;
      info[mp[_v]][ALPHA]--;
    }
    if (_c != '?') {
      info[mp[_v]][getIdx(_c)]++;
      info[mp[_v]][ALPHA]++;
    }
    if (c[_v] != _c) {
      update(mp[_v], getIdx(c[_v]), getIdx(_c));
      c[_v] = _c;
    }
    ask();
  }
  return 0;
}
