#include <bits/stdc++.h>
using namespace std;
struct node {
  node *fuck[26], *fail;
  int end;
  node() {
    for (int i = 0; i <= 25; i++) fuck[i] = NULL;
    fail = 0;
    end = 0;
  }
};
struct Trie {
  queue<node*> used;
  node* root;
  int L;
  inline node* newnode() {
    L++;
    node* temp = new node();
    used.push(temp);
    return temp;
  }
  void init() {
    L = 0;
    root = newnode();
  }
  void remove() {
    while (!used.empty()) {
      delete used.front();
      used.pop();
    }
  }
  void insert(string& buf) {
    int len = buf.size();
    node* now = root;
    for (int i = 0; i <= len - 1; i++) {
      int k = buf[i] - 'a';
      if (now->fuck[k] == NULL) now->fuck[k] = newnode();
      now = now->fuck[k];
    }
    now->end++;
  }
  void build() {
    queue<node*> Q;
    root->fail = root;
    for (int i = 0; i <= (26) - 1; i++) {
      if (root->fuck[i] == NULL)
        root->fuck[i] = root;
      else {
        root->fuck[i]->fail = root;
        Q.push(root->fuck[i]);
      }
    }
    while (!Q.empty()) {
      node* now = Q.front();
      Q.pop();
      now->end += now->fail->end;
      for (int i = 0; i <= (26) - 1; i++) {
        if (now->fuck[i] == NULL)
          now->fuck[i] = now->fail->fuck[i];
        else {
          now->fuck[i]->fail = now->fail->fuck[i];
          Q.push(now->fuck[i]);
        }
      }
    }
  }
  long long query(string& buf) {
    int len = buf.size();
    node* now = root;
    long long res = 0;
    for (int i = 0; i <= len - 1; i++) {
      now = now->fuck[buf[i] - 'a'];
      res += now->end;
    }
    return res;
  }
} tk;
vector<string> sr;
struct lowbAC {
  int modlist[(300000 + 1)];
  Trie t[(18)];
  void insert(int k, int ID) {
    modlist[k] = ID;
    int nid = k;
    int now = k, pre = k - 1, id = 0;
    while (now > 0) {
      if ((now & 1) != (pre & 1)) {
        if ((now & 1) == 1) {
          t[id].init();
          for (int _ = 1; _ <= (1 << id); _++) {
            t[id].insert(sr[modlist[nid] - 1]);
            nid--;
          }
          t[id].build();
        } else {
          t[id].remove();
        }
      }
      now >>= 1;
      pre >>= 1;
      id++;
    }
  }
  long long query(string& buf, int k) {
    long long ans = 0;
    for (int id = 0; k > 0; id++, k >>= 1)
      if ((k & 1) == 1) ans += t[id].query(buf);
    return ans;
  }
} ad, de;
char temp[(300000 + 1)];
int main(int argc, char* argv[]) {
  int n;
  scanf("%d", &n);
  int acnt = 1, dcnt = 1;
  for (int i = 1; i <= n; i++) {
    int ch;
    scanf("%d%s", &ch, temp);
    sr.push_back(string(temp));
    if (ch == 1) {
      ad.insert(acnt, i);
      acnt++;
    }
    if (ch == 2) {
      de.insert(dcnt, i);
      dcnt++;
    }
    if (ch == 3) {
      printf("%I64d\n",
             ad.query(sr[i - 1], acnt - 1) - de.query(sr[i - 1], dcnt - 1));
      fflush(stdout);
    }
  }
  return 0;
}
