#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
struct Hash {
  const static int md0 = 1e9 + 7, md1 = 1e9 + 9;
  int h0, h1;
  Hash(int h0 = 0, int h1 = 0) : h0(h0), h1(h1) {}
  Hash operator+(const int &o) const {
    return Hash((h0 + o) % md0, (h1 + o) % md1);
  }
  Hash operator*(const int &o) const {
    return Hash((h0 * 1ll * o) % md0, (h1 * 1ll * o) % md1);
  }
  Hash operator+(const Hash &o) const {
    return Hash((h0 + o.h0) % md0, (h1 + o.h1) % md1);
  }
  Hash operator-(const Hash &o) const {
    return Hash((h0 - o.h0 + md0) % md0, (h1 - o.h1 + md1) % md1);
  }
  Hash operator*(const Hash &o) const {
    return Hash((h0 * 1ll * o.h0) % md0, (h1 * 1ll * o.h1) % md1);
  }
  long long get() { return h0 * 1ll * md1 + h1; }
} has[maxn], pw[maxn], base = {131, 133};
map<long long, int> mp;
string ss[maxn], s;
int vis[maxn], n, m;
struct AC {
  int nxt[maxn][26], fail[maxn], num[maxn], cnt;
  int add() {
    ++cnt;
    memset(nxt[cnt], 0, sizeof nxt[cnt]);
    fail[cnt] = num[cnt] = 0;
    return cnt;
  }
  void init() {
    cnt = -1;
    add();
  }
  int insert(string &s) {
    int p = 0;
    for (int i = 0; i < ((int)s.size()); ++i) {
      int t = s[i] - 'a';
      if (!nxt[p][t]) nxt[p][t] = add();
      p = nxt[p][t];
    }
    ++num[p];
    return p;
  }
  void cFail() {
    queue<int> q;
    for (int i = 0; i < 26; ++i)
      if (int v = nxt[0][i]) q.push(v);
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      for (int i = 0; i < 26; ++i) {
        if (int v = nxt[u][i])
          fail[v] = nxt[fail[u]][i], num[v] += num[fail[v]], q.push(v);
        else
          nxt[u][i] = nxt[fail[u]][i];
      }
    }
  }
  long long ac(string &s) {
    cFail();
    long long ret = 0;
    int p = 0;
    for (int i = 0; i < ((int)s.size()); ++i) {
      p = nxt[p][s[i] - 'a'];
      ret += num[p];
    }
    return ret;
  }
} ac;
long long getH(string &s) {
  Hash h = 0;
  for (int i = 0; i < ((int)s.size()); ++i) {
    h = h * base + s[i];
  }
  return h.get();
}
long long getH(int l, int r) {
  Hash h = has[r] - has[l - 1] * pw[r - l + 1];
  return h.get();
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  pw[0] = {1, 1};
  for (int i = 1; i < maxn; ++i) pw[i] = pw[i - 1] * base;
  cin >> m;
  for (int i = 1; i <= m; ++i) {
    int opt;
    cin >> opt >> s;
    if (opt == 1) {
      ss[++n] = s;
      mp[getH(s)] = n;
      vis[n] = 1;
    } else if (opt == 2) {
      int p = mp[getH(s)];
      vis[p] = 0;
    } else {
      long long ret = 0;
      if (((int)s.size()) <= 600) {
        int tn = ((int)s.size());
        for (int i = 0; i < tn; ++i) {
          has[i + 1] = has[i] * base + s[i];
        }
        for (int i = 1; i <= tn; ++i) {
          for (int j = 1; j <= tn - i + 1; ++j) {
            long long h = getH(j, j + i - 1);
            if (mp.count(h)) ret += vis[mp[h]];
          }
        }
      } else {
        ac.init();
        for (int i = 1; i <= n; ++i) {
          if (vis[i]) ac.insert(ss[i]);
        }
        ret = ac.ac(s);
      }
      cout << ret << endl;
    }
  }
  return 0;
}
