#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
ifstream in("trie.in");
ofstream out("trie.out");
const int sigma = 26;
struct nodTrie {
int app,nr;
nodTrie *next[sigma];
nodTrie() {
nr = 0;
app = 0;
for (int i=0;i<26;++i) {
next[i] = nullptr;
}
}
} start;
void update(nodTrie*,const string&,int,int);
int queryApp(nodTrie*,const string&,int);
int queryMax(nodTrie*,const string&,int);
/*
void testFunc(int *ptr) {
*ptr = 2;
}
*/
int main() {
int tip;
string cuv;
/*
int x = 10;
int *ptr = &x;
testFunc(ptr);
cout<<x<<'\n';
//*/
/*
cuv = "da";
update(&start,cuv,0,1);
update(&start,cuv,0,-1);
//cuv = "dadadada";
//update(&start,cuv,0,1);
nodTrie aux = start;
aux = *aux.next['d'-'a'];
aux = *aux.next['a'-'a'];
cout<<aux.app<<'\n';
string cuv2 = "ddadaada";
cout<<queryMax(&start,cuv2,0)<<'\n';
//*/
//*
in>>tip;
while (!in.fail()) {
in>>cuv;
//cout<<tip<<' '<<cuv<<'\n';
if (tip == 0 || tip == 1) {
int add = (tip == 0) ? 1 : -1;
update(&start,cuv,0,add);
}
else if (tip == 2) {
out<<queryApp(&start,cuv,0)<<'\n';
}
else {
out<<queryMax(&start,cuv,0)<<'\n';
}
in>>tip;
}
/*
nodTrie *aux = &start;
aux = aux->next['a'-'a'];
aux = aux->next['b'-'a'];
aux = aux->next['a'-'a'];
//aux = aux->next['c'-'a'];
//aux = aux->next['a'-'a'];
cout<<aux->app<<'\n';
cout<<queryApp(&start,"lac",0);
//*/
in.close();out.close();
return EXIT_SUCCESS;
}
void update(nodTrie *nod,const string& cuv,int ind,int add) {
if (cuv.size() == ind) {
nod->app += add;
nod->nr += add;
return;
}
int val = cuv[ind] - 'a';
nodTrie *urm = nod->next[val];
if (urm == nullptr) {
urm = new nodTrie;
nod->next[val] = urm;
}
update(urm,cuv,ind+1,add);
nod->nr += add;
if (urm->nr == 0) {
delete urm;
nod->next[val] = nullptr;
}
}
int queryApp(nodTrie *nod,const string& cuv,int ind) {
if (cuv.size() == ind) {
return nod->app;
}
int val = cuv[ind] - 'a';
nodTrie *urm = nod->next[val];
if (urm == nullptr) {
return 0;
}
return queryApp(urm,cuv,ind+1);
}
int queryMax(nodTrie *nod,const string& cuv,int ind) {
if (cuv.size() == ind) {
return cuv.size();
}
int val = cuv[ind] - 'a';
nodTrie *urm = nod->next[val];
//int ret;
//ret = (nod->app != 0) ? ind : 0;
//ret = ind;
if (urm != nullptr) {
//ret = max(ret, queryMax(urm,cuv,ind+1));
return queryMax(urm,cuv,ind+1);
}
return ind;
//return ret;
}