#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
/* Represents a node in the trie data structure */
/* ================================================================================== */
struct TrieNode
{
int EndOfWord, Common;
char Letter;
TrieNode* Next[26];
TrieNode() { Common = 1; }
TrieNode(char ch) { Letter = ch; Common = 1; }
};
void AddWord(TrieNode* node, string word, int wordIndex)
{
if(wordIndex == word.length())
{
node->EndOfWord++;
return;
}
int index = word[wordIndex] - 'a';
if(node->Next[index] == nullptr)
node->Next[index] = new TrieNode(index + 'a');
else
node->Next[index]->Common++;
AddWord(node->Next[index], word, ++wordIndex);
}
bool TryGetNode(TrieNode* node, string word, int wordIndex, TrieNode& outNode)
{
if(wordIndex == word.length())
{
outNode = (*node);
return true;
}
int index = word[wordIndex] - 'a';
if(node->Next[index] == nullptr)
return false;
return TryGetNode(node->Next[index], word, ++wordIndex, outNode);
}
void RemoveNode(TrieNode* node, string word, int wordIndex)
{
if(wordIndex == word.length())
{
node->EndOfWord--;
node->Common--;
return;
}
int index = word[wordIndex] - 'a';
if(node->Next[index] == nullptr)
return;
RemoveNode(node->Next[index], word, ++wordIndex);
if(node->Next[index]->Common == 0)
{
delete node->Next[index];
node->Next[index] = nullptr;
}
}
/* ================================================================================== */
/* Draw an ugly representation of the trie */
/* stolen from ttps://www.geeksforgeeks.org */
/* ================================================================================== */
void printNTree(TrieNode* x, int depth = 0, bool isLast = false)
{
if (x == nullptr)
return;
for (int i = 1; i < depth; ++i)
cout << " ";
string amount = " x" + to_string(x->EndOfWord);
string common = " c" + to_string(x->Common);
amount += common;
if (depth == 0)
cout << x->Letter << amount << '\n';
else
cout << "+" << x->Letter << amount << '\n';
int it = 0;
for (int i = 0; i < 26; ++i, ++it)
printNTree(x->Next[i], depth + 1, it == 25);
}
/* ================================================================================== */
int GetLongestCommon(TrieNode* node, string word, int wordIndex, int depth = 0)
{
if(wordIndex == word.length())
return depth;
int index = word[wordIndex] - 'a';
if(node->Next[index] == nullptr)
return depth;
return GetLongestCommon(node->Next[index], word, ++wordIndex, depth + 1);
}
int main()
{
ifstream fin ("trie.in");
ofstream fout ("trie.out");
TrieNode* top = new TrieNode('*');
int number;
string word;
while(fin.good())
{
fin >> number, fin >> word;
switch(number)
{
case 0:
{
AddWord(top, word, 0);
break;
}
case 1:
{
RemoveNode(top, word, 0);
break;
}
case 2:
{
TrieNode ans;
bool found = TryGetNode(top, word, 0, ans);
fout << (found ? ans.EndOfWord : 0) << "\n";
break;
}
case 3:
{
//printNTree(top);
fout << GetLongestCommon(top, word, 0) << "\n";
break;
}
}
}
return 0;
}