Cod sursa(job #3192375)

Utilizator GiscaDianaGisca Diana Elena GiscaDiana Data 12 ianuarie 2024 14:32:32
Problema Trie Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.52 kb
#include <fstream>
#include <unordered_map>
#include <iostream>

struct TrieNode {
    std::unordered_map<char, TrieNode*> children; // Nodurile copil asociate caracterelor
    int ending_words; // Numărul de cuvinte care se termină la acest nod
    int passing_through; // Numărul de cuvinte care trec prin acest nod


    // Constructor cu valori implicite
    explicit TrieNode(int occurrences = 0, int passing_through = 0) :
        ending_words(occurrences),
        passing_through(passing_through) {}
};

// Clasa Trie pentru operații pe Trie
class Trie {
private:
    TrieNode* root = new TrieNode(); // Radacina Trie

public:
    // Inserarea unui cuvânt în Trie
    void insert (const std::string &word) {
        auto current_node = root;

        for (auto letter : word) {
            if (!current_node->children.count(letter)) {
                current_node->children[letter] = new TrieNode();
            }

            ++current_node->passing_through;
            current_node = current_node->children[letter];
        }

        ++current_node->passing_through;
        ++current_node->ending_words;
    }

    // Obținerea lungimii celui mai lung prefix comun între un cuvânt și oricare cuvânt din Trie
    int get_longest_common_prefix (const std::string &word) const {
        int common_prefix_length = 0;
        auto current_node = root;
        auto letter = word.begin();

        while (current_node->children.count(*letter)) {
            ++common_prefix_length;
            current_node = current_node->children[*letter];
            ++letter;
        }

        return common_prefix_length;
    }

    // Obținerea numărului de apariții ale unui cuvânt în Trie
    int get_occurrences (const std::string &word) const {
        auto current_node = root;

        for (auto letter : word) {
            if (!current_node->children.count(letter)) return 0;
            current_node = current_node->children[letter];
        }

        return current_node->ending_words;
    }

    // Eliminarea unui cuvânt din Trie
    void remove (const std::string &word) {
        auto current_node = root;
        auto letter = word.begin();

        while (letter != word.end()) {
            --current_node->passing_through;

            auto previous_node = current_node;
            current_node = current_node->children[*(letter++)];

            if (current_node->passing_through == 1) {
                previous_node->children.erase(*(letter - 1));
                previous_node = current_node;
            }

            if (previous_node->passing_through == 0) {
                delete previous_node;
            }
        }

        --current_node->passing_through;
        --current_node->ending_words;

        if (current_node->passing_through == 0) {
            delete current_node;
        }
    }
};

int main() {
    std::ifstream fin("trie.in");
    std::ofstream fout("trie.out");

    Trie trie;
    int operation;

    while (fin >> operation) {
        std::string word;
        fin >> word;

        switch (operation) {
            case 0:
                trie.insert(word);
                break;
            case 1:
                trie.remove(word);
                break;
            case 2:
                fout << trie.get_occurrences(word) << '\n';
                break;
            case 3:
                fout << trie.get_longest_common_prefix(word) << '\n';
                break;
        }
    }

    return 0;
}