#include <fstream>
std::ifstream fin("trie.in");
std::ofstream fout("trie.out");
struct Node {
std::unordered_map<char, Node*> letters;
int freq = 0;
void addWord(const std::string& word) {
Node* node = this;
int n = word.size();
for (int i = 0; i < n; i++) {
if (node->letters.find(word[i]) == node->letters.end()) {
node->letters[word[i]] = new Node{};
}
node = node->letters[word[i]];
}
node->freq++;
}
void eraseWord(const std::string& word) {
Node* node = this;
int n = word.size() - 1;
for (int i = 0; i < n; i++) {
if (node->letters.find(word[i]) == node->letters.end()) {
return;
}
node = node->letters[word[i]];
}
if (node->letters.find(word[n]) == node->letters.end()) {
return;
}
if (!--node->letters[word[n]]->freq) {
node->letters.erase(word[n]);
// TODO Delete
}
}
int count(const std::string& word) {
Node* node = this;
int n = word.size();
for (int i = 0; i < n; i++) {
if (node->letters.find(word[i]) == node->letters.end()) {
return 0;
}
node = node->letters[word[i]];
}
return node->freq;
}
int getPrefix(const std::string& word) {
Node* node = this;
int n = word.size();
for (int i = 0; i < n; i++) {
if (node->letters.find(word[i]) == node->letters.end()) {
return i;
}
node = node->letters[word[i]];
}
return n;
}
};
int main() {
Node* trie = new Node{};
int op;
std::string word;
while (fin >> op >> word) {
if (op == 0) {
trie->addWord(word);
} else if (op == 1) {
trie->eraseWord(word);
} else if (op == 2) {
fout << trie->count(word) << '\n';
} else if (op == 3) {
fout << trie->getPrefix(word) << '\n';
}
}
return 0;
}