#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct TrieNode
{
int pass;
int end;
vector<TrieNode*> nexts;
TrieNode()
:pass(0),end(0),nexts(26,nullptr) {};
};
class Trie
{
public:
Trie()
{
root = new TrieNode();
}
~Trie()
{
freeTrie(root);
}
void insert(const string& word)
{
TrieNode* node = root;
node->pass++;
for(auto ch : word)
{
int path = ch - 'a';
if(path < 0 || path >= 26) return;
if(node->nexts[path] == nullptr)
{
node->nexts[path] = new TrieNode();
}
node = node->nexts[path];
node->pass++;
}
node->end++;
}
void erase(const string& word)
{
if(search(word) > 0)
{
TrieNode* node = root;
node->pass--;
for(auto ch : word)
{
int path = ch - 'a';
if(path < 0 || path >= 26) return ;
if(--node->nexts[path]->pass == 0)
{
delete node->nexts[path];
node->nexts[path] = nullptr;
return;
}
node = node->nexts[path];
}
node->end--;
}
}
int search(const string& word)
{
TrieNode* node = root;
for(auto ch : word)
{
int path = ch - 'a';
if(path < 0 || path >=26 || node->nexts[path] == nullptr)
{
return 0;
}
node = node->nexts[path];
}
return node->end ;
}
int prefixNumber(string pre)
{
TrieNode* node = root;
for(auto ch : pre)
{
int path = ch - 'a';
if(path < 0 || path >= 26 || node->nexts[path] == nullptr)
{
return 0;
}
node = node->nexts[path];
}
return node->pass;
}
private:
void freeTrie(TrieNode* node)
{
if(node == nullptr)
{
return;
}
for(TrieNode* next : node->nexts)
{
freeTrie(next);
}
delete node;
}
private:
TrieNode* root;
};
int main() {
int op = 0;
string str;
int n = 0;
while(cin >> n)
{
Trie trie;
while(n--)
{
cin>>op>>str;
switch(op)
{
case 1:
trie.insert(str);
break;
case 2:
trie.erase(str);
break;
case 3:
cout << (trie.search(str) > 0 ? "YES" : "NO")<<endl;
break;
case 4:
cout << trie.prefixNumber(str) <<endl;
break;
}
}
}
}
// 64 位输出请用 printf("%lld")