#include <fstream>
#include <string>
#include <vector>
using namespace std;
ifstream cin ("trie.in");
ofstream cout ("trie.out");
struct TrieNode {
int end_count=0;
int prefix_count=0;
TrieNode* children[26]={nullptr};
};
void insert(TrieNode* root, const string& w) {
TrieNode* curr=root;
for (char c:w) {
int idx=c-'a';
if (!curr->children[idx]) {
curr->children[idx]=new TrieNode();
}
curr=curr->children[idx];
curr->prefix_count++;
}
curr->end_count++;
}
void remove(TrieNode* root, const string& w) {
TrieNode* curr=root;
for (char c:w) {
int idx=c-'a';
TrieNode* next_node=curr->children[idx];
next_node->prefix_count--;
if (next_node->prefix_count==0) {
curr->children[idx]=nullptr;
curr=next_node;
break;
}
curr=next_node;
}
curr->end_count--;
}
int count_word(TrieNode* root, const string& w) {
TrieNode* curr=root;
for (char c:w) {
int idx=c-'a';
if (!curr->children[idx] || curr->children[idx]->prefix_count==0) {
return 0;
}
curr=curr->children[idx];
}
return curr->end_count;
}
int longest_prefix(TrieNode* root, const string& w) {
TrieNode* curr=root;
int length=0;
for (char c:w) {
int idx=c-'a';
if (!curr->children[idx] || curr->children[idx]->prefix_count==0) {
break;
}
curr=curr->children[idx];
length++;
}
return length;
}
int main() {
int op;
string w;
TrieNode* root=new TrieNode();
while (cin>>op>>w) {
if (op==0) {
insert(root, w);
}
else if (op==1) {
remove(root, w);
}
else if (op==2) {
cout<<count_word(root, w)<<"\n";
}
else if (op==3) {
cout<<longest_prefix(root, w)<<"\n";
}
}
}