#include <iostream>
#include <fstream>
#include <unordered_map>
using namespace std;
class TrieNode
{
public:
TrieNode();
void add(string word);
void remove(string word);
int count(string word);
int prefix(string word);
private:
int endingHere;
int prefixCount;
unordered_map<char, TrieNode> children;
};
int main()
{
ios_base::sync_with_stdio(false);
freopen("trie.in", "r", stdin);
freopen("trie.out", "w", stdout);
int query;
string word;
TrieNode trie;
while (cin >> query)
{
cin.ignore(1);
getline(cin, word);
if (query == 0)
{
trie.add(word);
}
else if (query == 1)
{
trie.remove(word);
}
else if (query == 2)
{
cout << trie.count(word) << '\n';
}
else
{
cout << trie.prefix(word) << '\n';
}
}
}
TrieNode::TrieNode()
{
this->endingHere = 0;
this->prefixCount = 0;
this->children = {};
}
void TrieNode::add(string word)
{
auto current = this;
for (auto it = word.begin(); it != word.end(); ++it)
{
auto node = ¤t->children[*it];
current->children[*it] = *node;
current->prefixCount++;
current = node;
}
current->prefixCount++;
current->endingHere++;
// cout << word << " -> " << current->endingHere << endl;
};
void TrieNode::remove(string word)
{
auto current = this;
for (auto it = word.begin(); it != word.end(); ++it)
{
current->prefixCount--;
current = ¤t->children[*it];
}
current->prefixCount--;
current->endingHere--;
// cout << word << " -> " << current->endingHere << endl;
}
int TrieNode::count(string word)
{
auto current = this;
for (auto it = word.begin(); it != word.end(); ++it)
{
current = ¤t->children[*it];
}
return current->endingHere;
}
int TrieNode::prefix(string word)
{
auto current = this;
int prefix = 0;
for (auto it = word.begin(); it != word.end(); ++it)
{
auto node = current->children.find(*it);
if (node != current->children.end() && node->second.prefixCount > 0)
{
prefix++;
current = &node->second;
}
else
{
break;
}
}
return prefix;
}