#include <bits/stdc++.h>
using namespace std;
#define ALFA 26
class Trie;
class Node {
private:
int visited, word_end;
Node* son[ALFA];
public:
Node() {
this->visited = 0;
this->word_end = 0;
for (auto& node : son)
node = nullptr;
}
~Node() {
for (auto node : son)
delete node;
}
friend Trie;
};
class Trie {
private:
Node* root = nullptr;
const int offset = 'a';
int countAp(Node* current, string :: iterator left, string :: iterator right) {
if (left == right)
return current->word_end;
if (current->son[*left - offset] == nullptr)
return 0;
return countAp(current->son[*left - offset], left + 1, right);
}
void insertW(Node* current, string :: iterator left, string :: iterator right) {
if (left == right) {
current->word_end++;
return;
}
current->visited++;
if (current->son[*left - offset] == nullptr)
current->son[*left - offset] = new Node;
insertW(current->son[*left - offset], left + 1, right);
}
void deleteW(Node* current, string :: iterator left, string :: iterator right) {
if (left == right) {
current->word_end--;
delete current;
return;
}
deleteW(current->son[*left - offset], left + 1, right);
current->visited--;
if (current->visited == 0)
delete current;
}
int getPref(Node* current, string :: iterator left, string :: iterator right) {
if (current->visited < 2 || left == right)
return 0;
return 1 + getPref(current->son[*left - offset], left + 1, right);
}
public:
Trie() {
this->root = new Node;
}
int countAparitions(string word) {
return this->countAp(this->root, word.begin(), word.end());
}
void insertWord(string word) {
this->insertW(this->root, word.begin(), word.end());
}
void deleteWord(string word) {
if (this->countAparitions(word) == 0)
return;
this->deleteW(this->root, word.begin(), word.end());
}
int getLongestPrefix(string word) {
return this->getPref(this->root, word.begin(), word.end());
}
int countWords() {
return this->root->visited;
}
};
ifstream fin("trie.in");
ofstream fout("trie.out");
int main() {
Trie myTrie;
int task;
string S;
while (fin >> task >> S) {
switch (task) {
case 0:
myTrie.insertWord(S);
break;
case 1:
myTrie.deleteWord(S);
break;
case 2:
fout << myTrie.countAparitions(S) << "\n";
break;
case 3:
fout << myTrie.getLongestPrefix(S) << "\n";
break;
}
}
return 0;
}