Cod sursa(job #3354085)

Utilizator fmi-studentnu sunt de acord fmi-student Data 15 mai 2026 00:44:42
Problema Trie Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.42 kb
// proud of my over engineered baby
#include <iostream>
#include <cassert>
#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;
}