#include<cstdio>
#include<cstring>
using namespace std;
struct Node
{
Node *F[30];
int Nr,W;
Node()
{
memset(F,0,sizeof(F));
Nr = W = 0;
}
} *Trie;
void Get_Query(char Line[],int &t,char Word[])
{
t = Line[0] - '0';
strcpy(Word,Line + 2);
Word[strlen(Word) - 1]=0;
}
void Insert(char Word[])
{
char *p;
int c,l,i;
Node *Q = Trie;
Node *St[30];
for(p = Word, l = 0; *p; p++)
{
c = *p - 'a';
if(!Q->F[c]) Q->F[c] = new Node;
Q = Q->F[c];
St[++l] = Q;
}
Q->W++;
for(i = 1; i <= l; i++)
St[i]->Nr++;
}
void Delete(char Word[])
{
char *p;
int c,l,i;
Node *Q = Trie;
Node *St[30];
for(p = Word, l = 0; *p; p++)
{
c = *p - 'a';
Q = Q->F[c];
Q->Nr--;
St[++l] = Q;
}
Q->W--;
p--;
for(i = l; i >= 1; i--, p--)
if(!St[i]->Nr)
{
c = *p - 'a';
St[i-1]->F[c] = 0;
delete St[i];
}
else break;
}
int Query(char Word[])
{
return 0;
char *p;
int c;
Node *Q = Trie;
for(p = Word; *p; p++)
{
c = *p - 'a';
Q = Q->F[c];
}
return Q->W;
}
int Prefix_Lenght(char Word[])
{
char *p;
int c;
Node *Q = Trie;
for(p = Word; *p; p++)
{
c = *p - 'a';
if(!Q->F[c]) break;
Q = Q->F[c];
}
return p - Word;
}
int main()
{
int t;
char line[30],w[30];
freopen("trie.in","r",stdin);
freopen("trie.out","w",stdout);
Trie = new Node;
for(; fgets(line,30,stdin);)
{
Get_Query(line,t,w);
if(t == 0) Insert(w);
else if(t == 1) Delete(w);
else if(t == 2) printf("%d\n",Query(w));
else printf("%d\n",Prefix_Lenght(w));
}
return 0;
}