#include <bits/stdc++.h>
using namespace std;
const int MAXS = 300010, MAXQ = 300010, MAXH = 19;
struct node {
  node *ch[26], *fail;
  int mat;
} pool[MAXS + MAXH], *aval[MAXS + MAXH], *que[MAXS];
int aval_cnt;
inline node *add_node() { return aval[--aval_cnt]; }
struct ACM {
  node *root;
  void clear() {
    if (!root) return;
    int cur = aval_cnt;
    aval[aval_cnt++] = root;
    root = NULL;
    while (cur != aval_cnt) {
      node *u = aval[cur++];
      u->fail = NULL, u->mat = 0;
      for (int i = 0; i < 26; i++)
        if (u->ch[i]) {
          aval[aval_cnt++] = u->ch[i];
          u->ch[i] = NULL;
        }
    }
  }
  void extend(char *i) {
    node *u = root;
    for (; *i; i++) {
      int k = *i - 'a';
      if (!u->ch[k]) u->ch[k] = add_node();
      u = u->ch[k];
    }
    u->mat++;
  }
  void get_fail() {
    int begin = 0, end = 0;
    que[end++] = root;
    while (begin != end) {
      node *u = que[begin++];
      for (int i = 0; i < 26; i++) {
        if (!u->ch[i]) continue;
        node *p = u->fail;
        while (p && !p->ch[i]) p = p->fail;
        u->ch[i]->fail = (p ? p->ch[i] : root);
        u->ch[i]->mat += u->ch[i]->fail->mat;
        que[end++] = u->ch[i];
      }
    }
  }
  void build(int st, int ed, char **pos) {
    root = add_node();
    for (int i = st; i < ed; i++) extend(pos[i]);
    get_fail();
  }
  int query(char *i) {
    if (!root) return 0;
    int ret = 0;
    node *u = root;
    for (; *i; i++) {
      int k = *i - 'a';
      while (u && !u->ch[k]) u = u->fail;
      u = (u ? u->ch[k] : root);
      ret += u->mat;
    }
    return ret;
  }
} M[2][MAXH];
int n[2], q;
char str[2][MAXS << 1], edit[MAXS], *pos[2][MAXQ];
inline void init() {
  for (int i = 0; i < MAXS + MAXH; i++) aval[aval_cnt++] = pool + i;
}
inline void solve() {
  scanf("%d", &q);
  char *cur[2] = {str[0], str[1]};
  int opt;
  while (q--) {
    scanf("%d", &opt);
    if (opt == 3) {
      scanf("%s", edit);
      int ans = 0;
      for (int i = 0; i < MAXH; i++) ans += M[0][i].query(edit);
      for (int i = 0; i < MAXH; i++) ans -= M[1][i].query(edit);
      printf("%d\n", ans);
      fflush(stdout);
    } else {
      opt--;
      scanf("%s", cur[opt]);
      pos[opt][n[opt]++] = cur[opt];
      while (*cur[opt]) cur[opt]++;
      cur[opt]++;
      int x = n[opt] & -n[opt], f = 0;
      for (; (1 << f) < x; f++) M[opt][f].clear();
      M[opt][f].build(n[opt] - x, n[opt], pos[opt]);
    }
  }
}
int main() {
  init();
  solve();
  return 0;
}
