#include <cstdio>
#include <cstring>
class Node {
public:
int freq;
int sons;
Node* edges[26];
Node () {
freq = 0;
sons = 0;
for (int i = 0; i < 26; i++) {
edges[i] = 0;
}
}
static void addWord(char *s, int pos, Node* node, int length) {
if (pos == length) {
node->freq++;
return;
}
if (node->edges[s[pos] - 'a'] == 0) {
node->edges[s[pos] - 'a'] = new Node;
node->sons++;
}
addWord(s, pos + 1, node->edges[s[pos] - 'a'], length);
}
static bool deleteWord(char *s, int pos, Node *node, int length) {
if (pos == length) {
node->freq--;
if (node->freq == 0 && node->sons == 0 && pos != 0) {
delete node;
return true;
} else {
return false;
}
}
if (deleteWord(s, pos + 1, node->edges[s[pos] - 'a'], length)) {
node->sons--;
node->edges[s[pos] - 'a'] = 0;
}
if (node->freq == 0 && node->sons == 0 && pos != 0) {
delete node;
return true;
}
return false;
}
static int freqWord(char *s, int pos, Node *node, int length) {
if (pos == length) {
return node->freq;
}
if (node->edges[s[pos] - 'a'] == 0) {
return 0;
}
return freqWord(s, pos + 1, node->edges[s[pos] - 'a'], length);
}
static int maxPref(char *s, int pos, Node *node, int length) {
if (pos == length) {
return pos;
}
if (node->edges[s[pos] - 'a'] == 0) {
return pos;
}
return maxPref(s, pos + 1, node->edges[s[pos] - 'a'], length);
}
};
Node* root = new Node;
int main() {
freopen("trie.in", "r", stdin);
freopen("trie.out", "w", stdout);
int type;
while (scanf("%d", &type) != EOF) {
getc(stdin);
char s[25];
scanf("%s", s);
if (type == 0) {
Node::addWord(s, 0, root, (int)strlen(s));
} else if (type == 1) {
bool aux;
aux = Node::deleteWord(s, 0, root, (int)strlen(s));
} else if (type == 2) {
printf("%d\n", Node::freqWord(s, 0, root, (int)strlen(s)));
} else {
printf("%d\n", Node::maxPref(s, 0, root, (int)strlen(s)));
}
}
return 0;
}