#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
const int K = 26;
const int M = 20;
struct Node {
  vector<int> to;
  bool root;
  int p;
  int pchar;
  vector<int> go;
  int sum;
  int term;
  int suf_link;
  Node() {
    to = vector<int>(K, -1);
    go = vector<int>(K, -1);
    p = -1;
    suf_link = -1;
    pchar = -1;
    term = 0;
    root = false;
    sum = -1;
  }
};
vector<Node> node;
int roots[2][M];
vector<string> str[2][M];
void add(int root, string s) {
  int v = root;
  for (int i = 0; i < s.length(); i++) {
    int c = s[i] - 'a';
    if (node[v].to[c] == -1) {
      Node t;
      t.p = v;
      t.pchar = c;
      node[v].to[c] = node.size();
      node.push_back(t);
    }
    v = node[v].to[c];
  }
  node[v].term++;
}
int go(int v, int c);
int suf_link(int v) {
  if (node[v].suf_link != -1) return node[v].suf_link;
  if (node[v].root) {
    return node[v].suf_link = v;
  }
  if (node[node[v].p].root) {
    return node[v].suf_link = node[v].p;
  }
  return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}
int go(int v, int c) {
  if (node[v].go[c] != -1) return node[v].go[c];
  if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
  if (node[v].root) {
    return v;
  }
  return node[v].go[c] = go(suf_link(v), c);
}
int sum(int v) {
  if (node[v].sum != -1) return node[v].sum;
  node[v].sum = node[v].term;
  if (!node[v].root) node[v].sum += sum(suf_link(v));
  return node[v].sum;
}
long long calc(const string& s, int root) {
  long long ans = 0;
  int v = root;
  for (int i = 0; i < s.length(); i++) {
    int c = s[i] - 'a';
    v = go(v, c);
    ans += sum(v);
  }
  return ans;
}
long long result(string s) {
  long long ans = 0;
  for (int i = 0; i < M; i++) {
    if (str[0][i].size() != 0) {
      ans += calc(s, roots[0][i]);
    }
    if (str[1][i].size() != 0) {
      ans -= calc(s, roots[1][i]);
    }
  }
  return ans;
}
void clean(int v) {
  for (int i = 0; i < K; i++) {
    if (node[v].to[i] != -1) clean(node[v].to[i]);
  }
  node[v].go.clear();
  node[v].go.shrink_to_fit();
  node[v].to.clear();
  node[v].to.shrink_to_fit();
}
void insert(string s, int idx) {
  str[idx][0].push_back(s);
  int kk = -1;
  for (int k = 0; k < M; k++) {
    if (str[idx][k].size() == (1 << (k + 1))) {
      for (int i = 0; i < str[idx][k].size(); i++) {
        str[idx][k + 1].push_back(str[idx][k][i]);
      }
      str[idx][k].clear();
      clean(roots[idx][k]);
      roots[idx][k] = (int)node.size();
      node.push_back(Node());
      node.back().root = 1;
    } else {
      kk = k;
      break;
    }
  }
  assert(kk != -1);
  clean(roots[idx][kk]);
  roots[idx][kk] = (int)node.size();
  node.push_back(Node());
  node.back().root = 1;
  for (int i = 0; i < str[idx][kk].size(); i++) {
    add(roots[idx][kk], str[idx][kk][i]);
  }
}
char stroch[N];
int main() {
  for (int idx = 0; idx < 2; idx++) {
    for (int i = 0; i < M; i++) {
      roots[idx][i] = (int)node.size();
      node.push_back(Node());
      node.back().root = 1;
    }
  }
  int n;
  scanf(" %d", &n);
  for (int i = 0; i < n; i++) {
    int type;
    scanf(" %d", &type);
    scanf(" %s", stroch);
    string s = string(stroch);
    if (type != 3) {
      insert(s, type - 1);
    } else {
      printf(" %I64d\n", result(s));
      fflush(stdout);
    }
  }
  return 0;
}
