#include <bits/stdc++.h>
using namespace std;
const int SIGMA = 26;
struct Trie {
struct Node {
int edges[SIGMA];
int cnt;
int sum;
Node() {
cnt = 0;
sum = 0;
for ( int i = 0; i < SIGMA; i ++ ) edges[i] = 0;
}
};
Trie(): T(1) {}
vector <Node> T;
int createNode() {
T.resize( T.size() + 1 );
return T.size() - 1;
}
void add( int node, const string& s, int idx ) {
T[node].sum ++;
if ( idx == (int)s.size() ) {
T[node].cnt ++;
} else {
if ( T[node].edges[s[idx] - 'a'] == 0 ) {
T[node].edges[s[idx] - 'a'] = createNode();
}
add( T[node].edges[s[idx] - 'a'], s, idx + 1 );
}
}
void del( int node, const string& s, int idx ) {
T[node].sum --;
if ( idx == (int)s.size() ) {
T[node].cnt --;
} else {
del( T[node].edges[s[idx] - 'a'], s, idx + 1 );
}
}
int numCnt( int node, const string& s, int idx ) {
if ( idx == (int)s.size() ) {
return T[node].cnt;
} else {
if ( T[node].edges[s[idx] - 'a'] == 0 ) return 0;
return numCnt( T[node].edges[s[idx] - 'a'], s, idx + 1 );
}
}
int longestPref( int node, const string& s, int idx ) {
if ( T[node].sum == 0 ) return idx - 1;
if ( idx == (int)s.size() ) return idx;
if ( T[node].edges[s[idx] - 'a'] == 0 ) return idx;
return longestPref( T[node].edges[s[idx] - 'a'], s, idx + 1 );
}
};
int main() {
ifstream fin( "trie.in" );
ofstream fout( "trie.out" );
int op, root = 0;
string s;
Trie trie;
while ( fin >> op >> s ) {
if ( op == 0 ) {
trie.add( root, s, 0 );
} else if ( op == 1 ) {
trie.del( root, s, 0 );
} else if ( op == 2 ) {
fout << trie.numCnt( root, s, 0 ) << '\n';
} else {
fout << trie.longestPref( root, s, 0 ) << '\n';
}
}
return 0;
}