#include <fstream>
using namespace std;
ifstream fin("trie.in");
ofstream fout("trie.out");
struct nod
{
int nrcuv = 0, nrf = 0;
nod *f[26] = {};
};
class Trie
{
public:
nod *rad;
Trie()
{
rad = new nod;
}
~Trie()
{
delete rad;
// aici trebuia de fapt un pic mai complicat, dar whatever
}
void insert(nod *x, char *c)
{
if (c[0] == '\0')
x->nrcuv++;
else
{
if (x->f[c[0]-'a'] == NULL)
{
x->f[c[0]-'a'] = new nod;
x->nrf++;
}
insert(x->f[c[0]-'a'], c+1);
}
}
bool sterge(nod *x, char *c)
{
if (c[0] == '\0')
x->nrcuv--;
else
{
if (sterge(x->f[c[0]-'a'], c+1) == 1) //adică a avut loc dealocarea fiului corespunzător
{
x->f[c[0]-'a'] = NULL;
x->nrf--;
}
}
if (x->nrf == 0 && x->nrcuv == 0 && x != rad)
{
delete x;
return 1;
}
return 0;
}
int nrap(nod *x, char *c)
{
if (c[0] == '\0')
return x->nrcuv;
if (x->f[c[0]-'a'] == NULL)
return 0;
return nrap(x->f[c[0]-'a'], c+1);
}
int lgmax(nod *x, char *c)
{
if (c[0] == '\0')
return 0;
if (x->f[c[0]-'a'] == NULL)
return 0;
return 1 + lgmax(x->f[c[0]-'a'], c+1);
}
};
int main()
{
int tipq;
char w[21];
Trie t;
while (fin >> tipq >> w)
{
if (tipq == 0)
t.insert(t.rad, w);
else if (tipq == 1)
t.sterge(t.rad, w);
else if (tipq == 2)
fout << t.nrap(t.rad, w) << '\n';
else
fout << t.lgmax(t.rad, w) << '\n';
}
}