#include <fstream>
#include <cstring>
using namespace std;
ifstream fin("trie.in");
ofstream fout("trie.out");
struct trie{
int cnt, nrs;
trie *fiu[28];
trie() {
cnt = 0; nrs = 0;
memset(fiu, 0, sizeof(fiu));
}
};
trie *root = new trie();
int delta;
inline void Add(trie *node, char *s) {
if (*s == NULL) {
node->cnt++;
return;
}
delta = *s - 'a';
if (node->fiu[delta] == 0) {
node->nrs++;
node->fiu[delta] = new trie();
}
Add(node->fiu[delta], s + 1);
}
inline int Delete(trie *node, char *s) {
if (*s == 0) {
node->cnt--;
if (node->cnt == 0 && node->nrs == 0 && node != root) {
delete node;
return 1;
}
return 0;
}
delta = *s - 'a';
if (Delete(node->fiu[delta], s + 1)) {
node->nrs--; node->fiu[delta] = 0;
if (node->nrs == 0 && node->cnt == 0 && node != root) {
delete node;
return 1;
}
}
return 0;
}
inline int Query(trie *node, char *s) {
if (*s == 0)
return node->cnt;
delta = *s - 'a';
if (node->fiu[delta] == 0)
return 0;
return Query(node->fiu[delta], s + 1);
}
inline int Prefix(trie *node, char *s) {
if (*s == 0)
return 0;
delta = *s - 'a';
if (node->fiu[delta] == 0)
return 0;
return 1 + Prefix(node->fiu[delta], s + 1);
}
inline void Read() {
int tip; char s[22];
while (fin >> tip >> s) {
if (tip == 0) {
Add(root, s);
}
else if (tip == 1) {
Delete(root, s);
}
else if (tip == 2) {
fout << Query(root, s) << "\n";
}
else
fout << Prefix(root, s) << "\n";
}
}
int main () {
Read();
fin.close(); fout.close(); return 0;
}