#include <fstream>
#include <cstring>
#include <cstdlib>
#define lmax 25
using namespace std;
ifstream fin("trie.in");
ofstream fout("trie.out");
struct tnode
{
tnode *ch[26];
int words;
bool leaf;
int app;
tnode()
{
this->leaf = false;
this->app = 0;
this->words = 0;
memset(this->ch, 0, sizeof(this->ch));
}
};
tnode *trie;
char s[lmax], *p;
int qtype;
int maxx(int a, int b)
{
if (a>b)
{
return a;
}
return b;
}
bool existsInTrie(tnode *t, char *s)
{
if (!(*s))
{
return t->leaf;
}
if (!t->ch[*s-'a'])
{
return false;
}
return existsInTrie(t->ch[*s-'a'],s+1);
}
void insertInTrie(tnode *t, char *s, bool exists)
{
if (!(*s))
{
if (!exists)
{
t->leaf = true;
t->app = 1;
++t->words;
}
else
{
++t->app;
}
return;
}
if (!t->ch[*s-'a'])
{
t->ch[*s-'a'] = new tnode();
}
if (!exists)
{
++t->words;
}
insertInTrie(t->ch[*s-'a'], s+1, exists);
}
int cntApTrie(tnode *t, char *s)
{
if (!(*s))
{
return t->app;
}
return cntApTrie(t->ch[*s-'a'], s+1);
}
int largestPreff(tnode *t, char *s, int lg)
{
if (!(*s))
{
if (t->leaf)
{
return lg;
}
return 0;
}
if (!t->ch[*s-'a'])
{
return lg;
}
int v = largestPreff(t->ch[*s-'a'], s+1, lg+1);
v = maxx(v, lg);
return v;
}
bool deleteFromTrie(tnode *t, char *s)
{
if (!(*s))
{
--t->app;
if (!t->app)
{
t->leaf = false;
--t->words;
}
if (!t->words)
{
return true;
}
return false;
}
bool wasD = deleteFromTrie(t->ch[*s-'a'], s+1);
if (wasD)
{
delete t->ch[*s-'a'];
t->ch[*s-'a'] = NULL;
--t->words;
}
if (!t->words)
{
return true;
}
return false;
}
int main()
{
trie = new tnode();
while (fin.getline(s, lmax))
{
p = strtok(s, " ");
qtype = atoi(p);
p = strtok(NULL, " ");
bool ex = existsInTrie(trie, p);
if (qtype == 0)
{
insertInTrie(trie, p, ex);
//fout<<"Numar aparitii: "<<p<<" : "<<cntApTrie(trie, p)<<'\n';
}
else if (qtype == 1)
{
if (!ex)
{
continue;
}
deleteFromTrie(trie, p);
}
else if (qtype == 2)
{
if (!ex)
{
fout<<0<<'\n';
continue;
}
fout<<cntApTrie(trie, p)<<'\n';
}
else
{
fout<<largestPreff(trie, p, 0)<<'\n';
}
}
fin.close();
fout.close();
return 0;
}