#include <bits/stdc++.h>
#define int long long
#define cin ci
#define cout co
using namespace std;
ifstream cin("trie.in");
ofstream cout("trie.out");
const int nmax = 1e5;
struct Node
{
int fr, fin;
int edge[26] = {0};
};
vector<Node> trie;
string s;
int nodes = 1;
void add(int node, int pos)
{
trie[node].fr ++;
if(pos == (int)s.size())
{
trie[node].fin ++;
return;
}
int next = s[pos] - 'a';
if(!trie[node].edge[next])
{
trie[node].edge[next] = ++ nodes;
trie.push_back(Node());
}
add(trie[node].edge[next], pos + 1);
}
void rem(int node, int pos)
{
if(node == 0)
return;
trie[node].fr --;
if(pos == (int)s.size())
{
trie[node].fin --;
return;
}
int next = s[pos] - 'a';
rem(trie[node].edge[next], pos + 1);
if(trie[trie[node].edge[next]].fr == 0)
trie[node].edge[next] = 0;
}
int maxi = 0;
void query(int node, int pos)
{
if(node == 0)
return;
maxi = max(maxi, pos);
if(pos < (int)s.size())
{
int next = s[pos] - 'a';
query(trie[node].edge[next], pos + 1);
}
}
int numaps(int node, int pos)
{
if(node == 0)
return 0;
if(pos == (int)s.size())
return trie[node].fin;
int next = s[pos] - 'a';
return numaps(trie[node].edge[next], pos + 1);
}
int32_t main()
{
cin.tie(0);
ios_base::sync_with_stdio(0);
trie.push_back(Node());
trie.push_back(Node());
int c;
while (cin >> c >> s)
{
if (c == 0)
add(1, 0);
else if (c == 1)
rem(1, 0);
else if (c == 2)
cout << numaps(1, 0) << '\n';
else
{
maxi = 0;
query(1, 0);
cout << maxi << '\n';
}
}
return 0;
}