#include <bits/stdc++.h>
#define pb push_back
#define MAX 100000
#define mp make_pair
#define mod 1000000007
#define ll long long
#define ull unsigned long long
#define fastio ios_base::sync_with_stdio(NULL),cin.tie(NULL),cout.tie(NULL);
#define FILES freopen("trie.in","r",stdin);\
freopen("trie.out","w",stdout);
using namespace std;
int nodes,op;
string a,s;
struct Trie
{
int Go[30],fr[30];
bool isEnd;
};
vector<Trie> Tree;
void Insert(string a)
{
int s = 0;
for(int i = 0;i < a.size(); ++i)
{
int nex = Tree[s].Go[a[i]-'a'];
if(!nex)
{
Tree.pb(Trie());
nodes++;
Tree[s].Go[a[i]-'a'] = nodes;
Tree[s].fr[a[i]-'a']++;
s = nodes;
}
else
Tree[s].fr[a[i]-'a']++,s = nex;
}
Tree[s].isEnd = 1;
}
void Delete(string a)
{
int s = 0,cnt = 0;
for(int i = 0;i < a.size(); ++i)
{
int nex = Tree[s].Go[a[i]-'a'];
if(!Tree[s].fr[a[i]-'a']) return;
s = nex;
}
s = 0;
for(int i = 0;i < a.size(); ++i)
{
int nex = Tree[s].Go[a[i]-'a'];
Tree[s].fr[a[i]-'a']--;
s = nex;
}
}
inline int Occur(string a)
{
int s = 0,ans = 1e9;
for(int i = 0;i < a.size(); ++i)
{
ans = min(ans,Tree[s].fr[a[i]-'a']);
s = Tree[s].Go[a[i]-'a'];
}
for(int i = 'a';i <= 'z'; ++i)
ans -= Tree[s].fr[i-'a'];
if(ans < 0) ans = 0;
return ans;
}
inline int prefix(string a)
{
int s = 0, l = 0;
for(int i = 0;i < a.size(); ++i)
{
if(Tree[s].fr[a[i]-'a'])
l++;
else break;
s = Tree[s].Go[a[i]-'a'];
}
return l;
}
int main()
{
fastio
FILES
Tree.pb(Trie());
while(getline(cin,s))
{
a.clear();
op = s[0] - '0';
for(int j = 2;j < s.size(); ++j)
a += s[j];
if(!op) Insert(a);
else if(op == 1)
Delete(a);
else if(op == 2)
cout << Occur(a) << '\n';
else
cout << prefix(a) << '\n';
}
}