#include <fstream>
#include <vector>
#include <cstring>
using namespace std;
ifstream cin("trie.in");
ofstream cout("trie.out");
struct TrieNode
{
TrieNode *fii[30];
int aparitii = 0;
TrieNode()
{
for(int i = 0; i < 26; i++)
this->fii[i] = NULL;
}
};
int tip;
char s[30];
TrieNode *R = new TrieNode;
bool Gol(TrieNode *Node)
{
for(int i = 0; i < 26; i++)
if(Node->fii[i] != NULL)
return false;
return true;
}
void Inserare(char s[])
{
TrieNode *Curent_Node = R;
int n = strlen(s);
for(int i = 0; i < n; i++)
{
int lit = s[i] - 'a';
if(Curent_Node->fii[lit] == NULL)
Curent_Node->fii[lit] = new TrieNode;
Curent_Node = Curent_Node->fii[lit];
}
Curent_Node->aparitii++;
}
TrieNode* Stergere(TrieNode *Curent_Node, int pasi, char s[])
{
if(Curent_Node == NULL)
return NULL;
if(pasi == strlen(s))
{
if(Curent_Node->aparitii != 0)
Curent_Node->aparitii--;
if(Curent_Node->aparitii == 0 && Gol(Curent_Node))
{
delete (Curent_Node);
return NULL;
}
return Curent_Node;
}
int lit = s[pasi] - 'a';
Curent_Node->fii[lit] = Stergere(Curent_Node->fii[lit], pasi + 1, s);
if(Gol(Curent_Node) && Curent_Node->aparitii == 0)
{
delete (Curent_Node);
return NULL;
}
return Curent_Node;
}
int Aparitii(char s[])
{
TrieNode *Curent_Node = R;
int n = strlen(s);
for(int i = 0; i < n; i++)
{
int lit = s[i] - 'a';
if(Curent_Node->fii[lit] == NULL)
return 0;
Curent_Node = Curent_Node->fii[lit];
}
return Curent_Node->aparitii;
}
int Prefix_MAX(char s[])
{
TrieNode *Curent_Node = R;
int n = strlen(s);
for(int i = 0; i < n; i++)
{
int lit = s[i] - 'a';
if(Curent_Node->fii[lit] == NULL)
return i;
Curent_Node = Curent_Node->fii[lit];
}
return n;
}
int main()
{
while(cin >> tip >> s)
{
if(tip == 0)
Inserare(s);
else if(tip == 1)
R = Stergere(R, 0, s);
else if(tip == 2)
cout << Aparitii(s) << '\n';
else
cout << Prefix_MAX(s) << '\n';
}
return 0;
}