#include <bits/stdc++.h>
#pragma stacksize 10m
using namespace std;
const long double epsilon = 1e-9;
unsigned long long hashes[1 << 19];
unsigned long long powers[1 << 19];
int n;
string target;
int parents[1 << 19];
char characters[1 << 19];
int targetEnds[1 << 19];
vector<vector<int> > edges;
int totalLength;
int initialEdges[1 << 17];
string labels[1 << 17];
int degs[1 << 17];
int orderToProcess[1 << 17];
int endingIndex[1 << 17];
void calcInitialEdges() {
  memset(degs, 0, sizeof(degs));
  int charactersIdx = 0;
  totalLength = 0;
  for (int i = 1; i < n; i++) {
    cin >> initialEdges[i];
    cin >> labels[i];
    initialEdges[i]--;
    degs[initialEdges[i]]++;
    totalLength += labels[i].size();
  }
  queue<int> toProcess;
  for (int i = 0; i < n; i++) {
    if (degs[i] == 0) {
      toProcess.push(i);
    }
  }
  int cur;
  int idx = 0;
  while (!toProcess.empty()) {
    cur = toProcess.front();
    toProcess.pop();
    orderToProcess[idx++] = cur;
    if (--degs[initialEdges[cur]] == 0) {
      toProcess.push(initialEdges[cur]);
    }
  }
  reverse(orderToProcess, orderToProcess + n);
}
void calcRealEdges() {
  int idx = 0;
  edges.clear();
  edges.resize(totalLength);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < labels[orderToProcess[i]].size(); j++) {
      characters[idx] = labels[orderToProcess[i]][j];
      if (j == 0) {
        if (initialEdges[orderToProcess[i]] == 0) {
          parents[idx] = -1;
        } else {
          parents[idx] = endingIndex[initialEdges[orderToProcess[i]]];
          edges[endingIndex[initialEdges[orderToProcess[i]]]].push_back(idx);
        }
      } else {
        parents[idx] = idx - 1;
        edges[idx - 1].push_back(idx);
      }
      idx++;
    }
    if (idx > 0) endingIndex[orderToProcess[i]] = idx - 1;
  }
}
int dfsStack[1 << 19];
int dfsCntr = 0;
void dfsHelper(int idx) {
  if (dfsCntr >= (int)target.size()) {
    targetEnds[idx] = dfsStack[dfsCntr - ((int)target.size())];
  } else {
    targetEnds[idx] = -1;
  }
  for (int i = 0; i < edges[idx].size(); i++) {
    dfsStack[dfsCntr++] = edges[idx][i];
    dfsHelper(edges[idx][i]);
    dfsCntr--;
  }
}
void calcTargetEnds() {
  for (int i = 0; i < totalLength; i++) {
    targetEnds[i] = -2;
  }
  for (int i = 0; i < totalLength; i++) {
    if (targetEnds[i] == -2) {
      dfsStack[dfsCntr++] = i;
      dfsHelper(i);
      dfsCntr--;
    }
  }
}
set<int> candidates;
void doHash(int mod, int base) {
  powers[0] = 1;
  for (int i = 1; i < totalLength; i++) {
    powers[i] = (powers[i - 1] * base) % mod;
  }
  unsigned long long targetHash = 0;
  for (int i = 0; i < target.size(); i++) {
    targetHash = (targetHash * base + target[i] - 'a' + 1) % mod;
  }
  unsigned long long t;
  for (int i = 0; i < totalLength; i++) {
    if (parents[i] != -1)
      hashes[i] = (hashes[parents[i]] * base + characters[i] - 'a' + 1) % mod;
    else
      hashes[i] = characters[i] - 'a' + 1;
    if (targetEnds[i] != -1) {
      if (parents[targetEnds[i]] != -1) {
        t = (hashes[parents[targetEnds[i]]] * powers[target.size()]) % mod;
      } else {
        t = 0;
      }
      t = (hashes[i] - t + mod) % mod;
      if (t != targetHash) {
        candidates.erase(i);
      }
    }
  }
}
int main() {
  cin >> n;
  calcInitialEdges();
  calcRealEdges();
  cin >> target;
  calcTargetEnds();
  for (int i = 0; i < totalLength; i++) {
    if (targetEnds[i] != -1) {
      candidates.insert(i);
    }
  }
  doHash(1000000007, 29);
  doHash(1000000003, 31);
  doHash(1000000037, 37);
  cout << candidates.size() << endl;
  return 0;
}
