#include <iostream>
using namespace std;
const int NRL = 26;
const int MAX = 100000;
const int MAXL = 20;
char v[MAXL];
int siz;
struct node {
int nextp[NRL];
int fr, sp;//in fr tin cate cuvinte se termina acolo, in sp tin cate cuvinte au acel prefix
} trie[MAX];
int main()
{
FILE *fin, *fout;
int n, i, poz;
char ch, op;
fin = fopen("trie.in", "r");
op = fgetc(fin);
siz = 1;//1 este radacina
fout = fopen("trie.out", "w");
while (isdigit(op)) {
fscanf(fin, " ");
op -= '0';
ch = fgetc(fin);
n = 0;
while (isalpha(ch)) {
v[n] = ch - 'a';
ch = fgetc(fin);
n++;
}
poz = 1;
if (op == 0) {
for (i = 0; i < n; i++) {
trie[poz].sp++;
if (trie[poz].nextp[v[i]] == 0) {
siz++;
trie[poz].nextp[v[i]] = siz;
}
poz = trie[poz].nextp[v[i]];
}
trie[poz].fr++;
trie[poz].sp++;
} else if (op == 1) {
//sigur exista tot cuvantul
for (i = 0; i < n; i++) {
trie[poz].sp--;
poz = trie[poz].nextp[v[i]];
}
trie[poz].sp--;
trie[poz].fr--;
} else if (op == 2) {
for (i = 0; i < n; i++) {
poz = trie[poz].nextp[v[i]];
}
fprintf(fout, "%d\n", trie[poz].fr);
} else {
if (trie[1].sp == 0) {
fprintf(fout, "0\n");
} else {
i = 0;
while (i < n && trie[trie[poz].nextp[v[i]]].sp > 0) {
poz = trie[poz].nextp[v[i]];
i++;
}
fprintf(fout, "%d\n", i);
}
}
op = fgetc(fin);
}
fclose(fin);
fclose(fout);
return 0;
}