#include <bits/stdc++.h>
using namespace std;
struct trie {
  int ch[26], fail, cnt, ch2[26], sum;
} t[300001];
char ch[300001];
int root[2][300001], tot, num[2], n, q;
int head, tail, team[300001], dg[2][300001];
inline void build_trie(int x, int z) {
  root[z][x] = ++tot;
  int u = tot;
  for (int i = 1; i <= n; i++) {
    if (!t[u].ch[ch[i] - 'a']) t[u].ch[ch[i] - 'a'] = ++tot;
    u = t[u].ch[ch[i] - 'a'];
  }
  t[u].cnt++;
}
int merge(int u, int v) {
  if (!u || !v) return u | v;
  t[u].cnt += t[v].cnt;
  for (int i = 0; i < 26; i++) t[u].ch[i] = merge(t[u].ch[i], t[v].ch[i]);
  return u;
}
inline void get_fail(int rt) {
  head = 1, tail = 0;
  for (int i = 0; i < 26; i++)
    if (t[rt].ch[i]) {
      t[rt].ch2[i] = t[rt].ch[i];
      t[t[rt].ch[i]].fail = rt;
      team[++tail] = t[rt].ch[i];
    } else
      t[rt].ch2[i] = rt;
  while (head <= tail) {
    int x = team[head];
    for (int i = 0; i < 26; i++) {
      if (t[x].ch[i]) {
        t[x].ch2[i] = t[x].ch[i];
        t[t[x].ch[i]].fail = t[t[x].fail].ch2[i];
        team[++tail] = t[x].ch2[i];
      } else
        t[x].ch2[i] = t[t[x].fail].ch2[i];
    }
    t[x].sum = t[x].cnt + t[t[x].fail].sum;
    head++;
  }
}
void insert(int z) {
  build_trie(++num[z], z);
  dg[z][num[z]] = 1;
  while (dg[z][num[z]] == dg[z][num[z] - 1] && num[z] > 1) {
    num[z]--;
    dg[z][num[z]] += dg[z][num[z] + 1];
    root[z][num[z]] = merge(root[z][num[z]], root[z][num[z] + 1]);
  }
  get_fail(root[z][num[z]]);
}
int query(int z) {
  int ans = 0;
  for (int i = 1; i <= num[z]; i++) {
    int u = root[z][i];
    for (int j = 1; j <= n; j++) {
      u = t[u].ch2[ch[j] - 'a'];
      ans += t[u].sum;
    }
  }
  return ans;
}
int main() {
  int op;
  scanf("%d", &q);
  while (q--) {
    scanf("%d", &op);
    scanf("%s", ch + 1);
    n = strlen(ch + 1);
    if (op == 1 || op == 2) insert(op - 1);
    if (op == 3) printf("%d\n", query(0) - query(1));
    fflush(stdout);
  }
  return 0;
}
