#include <fstream>
#include <unordered_map>
#include <memory>
#include <string>
std::ifstream fin("trie.in");
std::ofstream fout("trie.out");
struct Node {
std::unordered_map<char, std::unique_ptr<Node>> letters;
int freq = 0;
void addWord(const std::string& word) {
Node* node = this;
for (char c : word) {
auto& next = node->letters[c];
if (!next)
next = std::make_unique<Node>();
node = next.get();
}
node->freq++;
}
bool eraseWord(const std::string& word, int i = 0) {
if (i == (int)word.size()) {
freq--;
} else {
auto it = letters.find(word[i]);
if (it == letters.end())
return false;
if (it->second->eraseWord(word, i + 1))
letters.erase(it);
}
return freq == 0 && letters.empty();
}
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]].get();
}
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]].get();
}
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;
}