#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f, oo = inf;
inline long long read() {
  register long long x = 0, f = 1;
  register char c = getchar();
  for (; !isdigit(c); c = getchar())
    if (c == '-') f = -1;
  for (; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
  return x * f;
}
inline void write(long long x) {
  if (x < 0) x = -x, putchar('-');
  if (x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}
inline void writeln(long long x) {
  write(x);
  puts("");
}
const int Mod = 1e9 + 7;
inline int ppow(int a, int b) {
  int ans = 1;
  for (; b; b >>= 1, a = 1ll * a * a % Mod)
    if (b & 1) ans = 1ll * ans * a % Mod;
  return ans;
}
const int maxnode = 323333;
struct ACautomto {
  struct node {
    int nxt[26], fail, v, end;
  } T[maxnode];
  int tot;
  int front, rear, q[maxnode], root[22];
  ACautomto() {
    tot = 0;
    memset(T, 0, sizeof(T));
  }
  inline void merge(int o1, int o2) {
    T[o2].end |= T[o1].end;
    for (register int i = (0); i < (26); ++i) {
      if (!T[o1].nxt[i])
        continue;
      else if (!T[o2].nxt[i])
        T[o2].nxt[i] = T[o1].nxt[i];
      else
        merge(T[o1].nxt[i], T[o2].nxt[i]);
    }
  }
  inline void insert(int o, char s[]) {
    for (int i = 0; s[i]; ++i) {
      if (!T[o].nxt[s[i] - 'a']) T[o].nxt[s[i] - 'a'] = ++tot;
      o = T[o].nxt[s[i] - 'a'];
    }
    ++T[o].end;
  }
  inline void build(int rt) {
    int u, v, p;
    front = rear = 0;
    q[rear++] = rt;
    while (front < rear) {
      u = q[front++];
      for (register int i = (0); i < (26); ++i)
        if (T[u].nxt[i]) {
          v = T[u].nxt[i], p = T[u].fail;
          while (p && !T[p].nxt[i]) p = T[p].fail;
          T[v].fail = p ? T[p].nxt[i] : rt;
          T[v].v = T[v].end + T[T[v].fail].v;
          q[rear++] = v;
        }
    }
  }
  inline int query(int rt, char s[]) {
    int ans = 0, o = rt;
    for (int i = 0; s[i]; ++i) {
      while (o && !T[o].nxt[s[i] - 'a']) o = T[o].fail;
      if (o == 0) o = rt;
      o = T[o].nxt[s[i] - 'a'];
      ans += T[o].v;
    }
    return ans;
  }
  inline void add(char s[]) {
    int rt = ++tot;
    insert(rt, s);
    for (int i = 0; i < 20; ++i) {
      if (!root[i]) {
        root[i] = rt;
        build(root[i]);
        return;
      } else {
        merge(root[i], rt);
        root[i] = 0;
      }
    }
  }
  inline int get(char s[]) {
    int ans = 0;
    for (int i = 0; i < 20; ++i) ans += query(root[i], s);
    return ans;
  }
} add, del;
char s[300005];
int main() {
  int T = read();
  while (T--) {
    int op = read();
    scanf("%s", s);
    if (op == 1) {
      add.add(s);
    } else if (op == 2) {
      del.add(s);
    } else {
      writeln(add.get(s) - del.get(s));
    }
    fflush(stdout);
  }
  return 0;
}
