#include <bits/stdc++.h>
using namespace std;
ifstream fin("trie.in");
ofstream fout("trie.out");
struct Trie{
int nr, sons;
Trie *fii[26];
Trie(){
nr = sons = 0;
memset(fii, 0, sizeof(fii));
}
};
Trie *T = new Trie;
void Add(Trie *nod, char *s)
{
if(*s == NULL)
{
nod->nr++;
return;
}
if(nod->fii[(*s-'a')] == 0)
{
nod->fii[(*s-'a')] = new Trie;
nod->sons++;
}
Add(nod->fii[(*s-'a')], s+1);
}
bool Delete(Trie *nod, char *s)
{
if(*s == NULL)
{
if(nod->nr)
nod->nr--;
}
else if(Delete(nod->fii[(*s-'a')], s+1))
{
nod->fii[(*s-'a')] = 0;
nod->sons--;
}
if(nod->nr == 0 && nod->sons == 0 && nod!=T)
{
delete nod; return 1;
}
return 0;
}
int Query(Trie *nod, char *s)
{
if(*s == NULL)
{
return nod->nr;
}
if(nod->fii[(*s-'a')])
return Query(nod->fii[(*s-'a')], s+1);
return 0;
}
int Prefix(Trie *nod, char *s, int k)
{
if(*s == NULL || nod->fii[(*s-'a')] == 0)
return k;
return Prefix(nod->fii[(*s-'a')], s+1, k+1);
}
int main()
{
short w;
char ch[25];
while(fin>>w>>ch)
{
if(w == 0)
Add(T, ch);
else
if(w == 1)
Delete(T, ch);
else
if(w == 2)
fout << Query(T, ch) << '\n';
else
fout << Prefix(T, ch, 0) << '\n';
}
return 0;
}