#include <bits/stdc++.h>
using namespace std;
struct __s {
  __s() {
    srand(time(NULL));
    if (1) {
      ios_base::Init i;
      cin.sync_with_stdio(0);
      cin.tie(0);
    }
  }
  ~__s() {
    if (!1)
      fprintf(stderr, "Execution time: %.3lf s.\n",
              (double)clock() / CLOCKS_PER_SEC);
    int n;
    cin >> n;
  }
} __S;
struct vertex {
  int go[26];
  int link;
  int ans;
  int p;
  int pch;
  bool root;
  bool isAns;
  vertex(int p, int pch, bool root) : p(p), pch(pch), root(root) {
    memset(go, 255, sizeof(go));
    link = -1;
    ans = 0;
    isAns = false;
  };
};
vector<vertex> t;
void add(string &s, int v) {
  for (int i = 0; i < (int)(s.size()); i++) {
    int c = s[i] - 'a';
    if (t[v].go[c] == -1) {
      t[v].go[c] = t.size();
      t.push_back(vertex(v, c, false));
    }
    v = t[v].go[c];
  }
  t[v].ans++;
}
int getGo(int v, int c);
int getLink(int v) {
  if (t[v].link == -1) {
    if (t[t[v].p].root)
      return t[v].link = t[v].p;
    else
      return t[v].link = getGo(getLink(t[v].p), t[v].pch);
  }
  return t[v].link;
}
int getGo(int v, int c) {
  if (t[v].go[c] == -1) {
    if (t[v].root)
      return t[v].go[c] = v;
    else
      return t[v].go[c] = getGo(getLink(v), c);
  }
  return t[v].go[c];
}
int getAns(int v) {
  if (t[v].isAns) return t[v].ans;
  t[v].isAns = true;
  return t[v].ans += getAns(getLink(v));
}
int getAns(string &s, int v) {
  int res = 0;
  for (int i = 0; i < (int)(s.size()); i++) {
    int c = s[i] - 'a';
    v = getGo(v, c);
    res += getAns(v);
  }
  return res;
}
int n[2];
int root[2][20];
queue<string> p[2][20];
queue<string> q[2];
void build() {
  for (int i = 0; i < (int)(2); i++) {
    int N = n[i] + q[i].size();
    for (int j = 0; j < (int)(20); j++) {
      bool a = ((n[i] >> j) & 1);
      bool b = ((N >> j) & 1);
      if (a == b) continue;
      if (a) {
        root[i][j] = 0;
        while (p[i][j].size()) {
          q[i].push(p[i][j].front());
          p[i][j].pop();
        }
        continue;
      }
      root[i][j] = t.size();
      t.push_back(vertex(root[i][j], 0, true));
      for (int k = 0; k < (int)(1LL << j); k++) {
        add(q[i].front(), root[i][j]);
        p[i][j].push(q[i].front());
        q[i].pop();
      }
    }
    n[i] = N;
  }
}
int get(string &s, int i) {
  int res = 0;
  for (int j = 0; j < (int)(20); j++) {
    if (root[i][j] == 0) continue;
    res += getAns(s, root[i][j]);
  }
  return res;
}
int get(string &s) { return get(s, 0) - get(s, 1); }
int main(void) {
  t.push_back(vertex(0, 0, false));
  int n;
  cin >> n;
  for (int _ = 0; _ < (int)(n); _++) {
    int t;
    string s;
    cin >> t >> s;
    if (t == 1 || t == 2) {
      q[t - 1].push(s);
    } else {
      build();
      cout << get(s) << '\n';
      cout.flush();
    }
  }
  return 0;
}
