#include <bits/stdc++.h>
using namespace std;
const int MAX = 3e5 + 10;
const int BLOCK = 600;
int q, type, len, f[MAX];
long long res;
vector<pair<string, int> > str;
char s[MAX];
struct NodeTrie {
  int sum;
  NodeTrie *link[26];
  NodeTrie() : sum(0) { memset(link, NULL, sizeof(link)); }
  static NodeTrie *root;
  static void insert(const int &len, const int &val, char *s) {
    NodeTrie *cur = root;
    for (int i = 0; i < len; ++i) {
      if (cur->link[s[i] - 'a'] == NULL) cur->link[s[i] - 'a'] = new NodeTrie;
      cur = cur->link[s[i] - 'a'];
    }
    cur->sum += val;
  }
  static int get(const int &len, char *s) {
    int res = 0;
    NodeTrie *cur = root;
    for (int i = 0; i < len; ++i) {
      if (cur->link[s[i] - 'a'] == NULL) break;
      cur = cur->link[s[i] - 'a'];
      res += cur->sum;
    }
    return res;
  }
};
NodeTrie *NodeTrie::root = new NodeTrie;
void ConstructFSM(string &t) {
  f[0] = -1;
  for (int i = 1; i <= t.length(); ++i) {
    int j = f[i - 1];
    while (j >= 0 && t[j] != t[i - 1]) j = f[j];
    f[i] = j + 1;
  }
}
int main() {
  scanf("%d", &q);
  while (q--) {
    scanf("%d %s", &type, s);
    len = strlen(s);
    if (type == 1 || type == 2) {
      if (len < BLOCK)
        NodeTrie::insert(len, 3 - 2 * type, s);
      else
        str.push_back(pair<string, int>(s, 3 - 2 * type));
    } else {
      res = 0;
      for (int i = 0; i < len; ++i) res += NodeTrie::get(len - i, s + i);
      for (pair<string, int> &t : str)
        if (t.first.length() <= len) {
          ConstructFSM(t.first);
          int j = 0;
          for (int i = 1; i <= len; ++i) {
            while (j >= 0 && t.first[j] != s[i - 1]) j = f[j];
            ++j;
            if (j == t.first.length()) {
              res += t.second;
              j = f[j];
            }
          }
        }
      printf("%lld\n", res);
      fflush(stdout);
    }
  }
  return 0;
}
