#include <bits/stdc++.h>
using namespace std;
struct AhoCorasick {
  struct node : public map<char, int> {
    int link = 0, cnt = 0;
  };
  vector<node> t;
  AhoCorasick(vector<string> &S) : t(1) {
    for (string &s : S) {
      int v = 0;
      for (char c : s) {
        if (!t[v].count(c)) t[v][c] = t.size(), t.emplace_back();
        v = t[v][c];
      }
      t[v].cnt++;
    }
    queue<int> q({0});
    while (!q.empty()) {
      int p = q.front();
      q.pop();
      for (auto g : t[p]) {
        char c = g.first;
        int pp = g.second;
        int k = t[p].link;
        while (k && !t[k].count(c)) k = t[k].link;
        if (t[k].count(c)) k = t[k][c];
        t[pp].link = p == 0 ? 0 : k;
        t[pp].cnt += t[t[pp].link].cnt;
        q.push(pp);
      }
    }
  }
  int query(string &s) {
    int v = 0, ans = 0;
    for (char c : s) {
      while (v && !t[v].count(c)) v = t[v].link;
      v = t[v][c];
      ans += t[v].cnt;
    }
    return ans;
  }
};
struct AhoItem {
  vector<string> s;
  AhoCorasick aho;
  AhoItem(string &S) : s{S}, aho{s} {}
  AhoItem(vector<string> &&S) : s{S}, aho{s} {}
};
struct SqrtDecomposition {
  int bound, size = 0, cur = 0;
  vector<AhoItem> blocks;
  SqrtDecomposition(int bound) : bound(bound) {}
  void insert(AhoItem &&item) {
    size++;
    blocks.push_back(item);
    if (++cur == bound) {
      blocks.push_back(pop(cur));
      cur = 0;
    }
  }
  int query(string &s) {
    int ans = 0;
    for (auto &b : blocks) ans += b.aho.query(s);
    return ans;
  }
  AhoItem pop(int num) {
    vector<string> s;
    while (num--) {
      s.insert(s.end(), make_move_iterator(blocks.back().s.begin()),
               make_move_iterator(blocks.back().s.end()));
      blocks.pop_back();
    }
    return s;
  }
  AhoItem clear() {
    size = 0;
    return pop(blocks.size());
  }
};
struct InsertAho {
  int c;
  vector<SqrtDecomposition> magic;
  InsertAho(int k = 8, int c = 3) : c(c) {
    for (int i = 0; i < k; i++) magic.emplace_back(c);
  }
  void insert(string &s) {
    magic[0].insert({s});
    for (size_t i = 0; i + 1 < magic.size(); i++)
      if (magic[i].size == c * c) magic[i + 1].insert(magic[i].clear());
  }
  int query(string &s) {
    int ans = 0;
    for (size_t i = 0; i < magic.size(); i++) ans += magic[i].query(s);
    return ans;
  }
};
struct RemoveAho {
  InsertAho in, out;
  void insert(string &s) { in.insert(s); }
  void remove(string &s) { out.insert(s); }
  int query(string &s) { return in.query(s) - out.query(s); }
} aho;
int main() {
  ios_base::sync_with_stdio(false);
  int m;
  cin >> m;
  while (m--) {
    int t;
    string s;
    cin >> t >> s;
    if (t == 1)
      aho.insert(s);
    else if (t == 2)
      aho.remove(s);
    else
      cout << aho.query(s) << endl;
  }
  return 0;
}
