Pagini recente » Diferente pentru problema/teste intre reviziile 33 si 32 | Cod sursa (job #2886293) | Cod sursa (job #3129490) | Cod sursa (job #2019540) | Cod sursa (job #3354086)
// proud of my over engineered baby
#include <iostream>
#include <cassert>
#include <memory>
#include <fstream>
using namespace std;
// schimbam stilul de numit clase de la STL la propriu
class Trie {
public:
static const char ASCII_START = 'a';
static const char ASCII_END = 'z';
protected:
class Node {
protected:
char value;
int end_of_word;
int pass_count;
vector<shared_ptr<Node>> next;
public:
Node(char value) :
value(value),
end_of_word(0),
pass_count(0),
next(Trie::ASCII_END - Trie::ASCII_START + 1, nullptr) {}
void set_eow(int eow) {
end_of_word = eow;
}
int get_eow() const {
return end_of_word;
}
void increment_pass() {
++pass_count;
}
void decrement_pass() {
--pass_count;
}
int get_pass() const {
return pass_count;
}
shared_ptr<Node> get_node(size_t i) const {
return next[i];
}
void add_node(size_t i, char val) {
next[i] = make_shared<Node>(val);
}
void remove_node(size_t i) {
next[i] = nullptr;
}
bool has_children() const {
for(const auto& child : next)
if(child)
return true;
return false;
}
};
shared_ptr<Node> root;
size_t char_to_index(char ch) {
ch = tolower(ch);
assert(ch >= ASCII_START);
assert(ch <= ASCII_END);
return static_cast<size_t>(tolower(ch) - ASCII_START);
}
bool erase_recursive(shared_ptr<Node> current, const string_view& s, size_t depth) {
if (!current)
return false;
if (depth == s.size()) {
if (!current->get_eow())
return false;
current->set_eow(current->get_eow() - 1);
current->decrement_pass();
return true;
}
size_t i = char_to_index(s[depth]);
if (erase_recursive(current->get_node(i), s, depth + 1)) {
current->decrement_pass();
// not used by anyone, free to delete
if (current->get_node(i)->get_pass() == 0)
current->remove_node(i);
return true;
}
return false;
}
public:
Trie() : root(make_shared<Node>('\0')) {}
void insert(const string_view& s) {
shared_ptr<Node> parser = root;
parser->increment_pass();
for (char ch : s) {
size_t i = char_to_index(ch);
if (!parser->get_node(i)) {
parser->add_node(i, ch);
}
parser = parser->get_node(i);
parser->increment_pass();
}
parser->set_eow(parser->get_eow() + 1);
}
void erase(const string_view& s) {
erase_recursive(root, s, 0);
}
size_t longest_prefix(const string_view& s) {
shared_ptr<Node> parser = root;
size_t length = 0;
for (char ch : s) {
size_t i = char_to_index(ch);
auto next_node = parser->get_node(i);
if (!next_node)
break;
parser = next_node;
++length;
}
return length;
}
int count(const string_view& s) {
shared_ptr<Node> parser = root;
for (char ch : s) {
size_t i = char_to_index(ch);
parser = parser->get_node(i);
if (!parser)
return 0;
}
return parser->get_eow();
}
};
int main() {
ifstream fin("trie.in");
if (!fin.is_open()) {
cerr << "trie.in failed to open!" << endl;
return 1;
}
ofstream fout("trie.out");
if (!fout.is_open()) {
cerr << "trie.out failed to open!" << endl;
return 2;
}
Trie trie;
int op;
string word;
while (fin >> op >> word) {
switch (op) {
case 0:
trie.insert(word);
break;
case 1:
trie.erase(word);
break;
case 2:
fout << trie.count(word) << "\n";
break;
case 3:
fout << trie.longest_prefix(word) << "\n";
break;
default:
break;
}
}
fin.close();
fout.close();
return 0;
}