#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
typedef unsigned int uint;
uint sz;
struct TrieNode{
bool fullWord;
int wordNumber,fullWordNo;
TrieNode *links[26];
};
TrieNode* createInstance(){
TrieNode *node = new TrieNode;
node->fullWord = false;
node->wordNumber = 0;
node->fullWordNo = 0;
for(int i = 0; i < 26; i++)
node->links[i] = NULL;
return node;
}
void add(TrieNode * root,const char word[]){
TrieNode* current = root;
for(uint i = 0; i < sz; i++){
if(current->links[word[i] - 'a'] == NULL)
current->links[word[i] - 'a'] = createInstance();
current = current->links[word[i] - 'a'];
current->wordNumber++;
}
current->fullWord = true;
current->fullWordNo++;
}
void deleteNode(TrieNode* root, const char word[],uint index){
if(index < sz){
deleteNode(root->links[word[index] - 'a'],word,index + 1);
if(root->links[word[index] - 'a']->wordNumber > 1){
root->links[word[index] - 'a']->wordNumber--;
if(index == sz - 1 && root->links[word[index] - 'a']->fullWord){
root->links[word[index] - 'a']->fullWordNo--;
}
if(root->links[word[index] - 'a']->fullWordNo < 1)
root->links[word[index] - 'a']->fullWord = false;
}
else{
delete root->links[word[index] - 'a'];
root->links[word[index] - 'a'] = NULL;
}
}
}
void prefix(TrieNode* root, const char w[]){
int mxm = 0;
for(uint i = 0; i < sz; i++){
root = root->links[w[i] - 'a'];
if(root != NULL){
mxm++;
}
else
break;
}
printf("%d\n",mxm);
}
void wordCount(TrieNode* root,const char w[]){
int mxm = 0;
for(uint i = 0; i < sz; i++){
if(root->links[w[i] - 'a'] == NULL)
break;
root = root->links[w[i] - 'a'];
}
mxm = root->fullWordNo;
printf("%d\n",mxm);
}
int main(){
freopen("trie.in","r",stdin);
freopen("trie.out","w",stdout);
string str;
int q;
TrieNode* root = createInstance();
// int c = 0,idx = 0;
while(cin>>q>>str){
// idx++;
// cout<<idx<< " " <<str<<" ";
sz = str.size();
if(q == 0){
add(root,str.c_str());
}
if(q == 1)
deleteNode(root,str.c_str(),0);
if(q == 2){
wordCount(root,str.c_str());
}
if(q == 3){
prefix(root,str.c_str());
}
/* sz = 8;
string s = "dezvinui";
cout<<"---Dezvinui = ";
wordCount(root,s.c_str());
// if(c == 107)
// cout<<"index = "<<idx<< " "<<str<<" " << q<<'\n';*/
}
return 0;
}
/*
TrieNode* createInstance(){
TrieNode *node = new TrieNode;
node->fullWord = false;
node->wordNumber = 0;
node->fullWordNo = 0;
for(int i = 0; i < 26; i++)
node->links[i] = NULL;
return node;
}
void add(TrieNode* root,const char w[],int sz){
TrieNode* current = root;
int offset = 97;
for(uint i = 0; i < sz; i++){
if(current->links[w[i] - offset] == NULL)
current->links[w[i] - offset] = createInstance();
current = current->links[w[i] - offset];
current->wordNumber++;
}
current->fullWordNo ++;
current->fullWord = true;
}
void print(TrieNode* root, char branch[],int level){
if(root->fullWord == true){
for(int i = 0; i < level;i++)
cout<<branch[i];
cout<<'\n';
}
for(int i = 0; i < 26; i++){
if(root->links[i] != NULL){
branch[level] = i + 'a';
print(root->links[i],branch,level + 1);
}
}
}
void findWord(TrieNode *root,const char word[],int sz){
for(uint i = 0; i < sz; i++){
if(root->links[word[i] - 'a'] != NULL)
root = root->links[word[i] - 'a'];
else{
printf("0\n");
return;
}
}
if(root->fullWord)
printf("%d\n", root->fullWordNo);
else
printf("0\n");
}
void longestPrefix(TrieNode *root,const char word[],int sz){
int maxim = 0;
for(uint i = 0; i < sz; i++){
if(root->links[word[i] - 'a'] != NULL){
root = root->links[word[i] - 'a'];
maxim++;
}
else
break;
}
printf("%d\n", maxim);
}
void deleteWord(TrieNode *root, const char w[],uint index,int sz){
if(index < sz){
deleteWord(root->links[w[index] - 'a'],w,index + 1,sz);
// if(index < w.size()){
if(root->links[w[index] - 'a']->fullWord == true && root->links[w[index] - 'a']->fullWordNo > 1)
root->links[w[index] - 'a']->fullWordNo--;
if(root->links[w[index] - 'a']->wordNumber > 1)
root->links[w[index] - 'a']->wordNumber--;
else{
free(root->links[w[index] - 'a']);
root->links[w[index] - 'a'] = NULL;
}
// }
}
}
int main(){
freopen("trie.in","r",stdin);
freopen("trie.out","w",stdout);
string str;
int q;
TrieNode* root = createInstance();
int c = 0,idx = 0;
while(cin>>q>>str){
idx++;
if(q == 0){
add(root,str.c_str(),str.size());
}
if(q == 1){
deleteWord(root,str.c_str(),0,str.size());
// char branch[20];
// print(root,branch,0);
}
if(q == 2){
// if(str == "abac")
// cout<<"A";
// char branch[20];
// print(root,branch,0);
if(str == "dezvinui")
cout<<"brak";
findWord(root,str.c_str(),str.size());
c++;
}
if(q == 3){
longestPrefix(root,str.c_str(),str.size());
c++;
}
if(c == 107)
cout<<"index = "<<idx<< " "<<str<<" " << q<<'\n';
}
return 0;
}*/