#include <fstream>
#include <cstring>
#define ch(poz) (s[poz] - 'a')
using namespace std;
ifstream cin ("trie.in");
ofstream cout ("trie.out");
int n, t;
string s;
struct Trie {
int val, nr;
Trie* nxt[26];
Trie() {
val = nr = 0;
for(int i = 0; i < 26; i++)
nxt[i] = 0;
}
} *R;
void insert(Trie* T, int poz) {
if(poz == s.size()) {
T->val++;
return;
}
if(T->nxt[ch(poz)] == 0) {
T->nxt[ch(poz)] = new Trie;
T->nr++;
}
insert(T->nxt[ch(poz)], poz + 1);
}
int erase(Trie *T, int poz) {
if(poz == s.size())
T->val--;
else if(erase(T->nxt[ch(poz)], poz + 1)) {
T->nxt[ch(poz)] = 0;
T->nr--;
}
if(!T->val && !T->nr && T != R) {
delete T; return 1;
}
return 0;
}
int query(Trie* T, int poz) {
if(poz == s.size())
return T->val;
if(T->nxt[ch(poz)])
return query(T->nxt[ch(poz)], poz + 1);
return 0;
}
int lcp(Trie* T, int poz, int lg) {
if(poz == s.size() || T->nxt[ch(poz)] == 0)
return lg;
return lcp(T->nxt[ch(poz)], poz + 1, lg + 1);
}
int main() {
R = new Trie;
while(cin >> t >> s) {
if(t == 0)
insert(R, 2);
else if(t == 1)
erase(R, 2);
else if(t == 2)
cout << query(R, 2) << "\n";
else
cout << lcp(R, 2, 0) << "\n";
}
return 0;
}