Cod sursa(job #3184914)

Utilizator RaresParleaParlea Costin-Rares-Calin RaresParlea Data 17 decembrie 2023 12:55:31
Problema Trie Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.04 kb
#include <fstream>
#include <unordered_map>
#include <iostream>

struct TrieNode {
    std::unordered_map<char, TrieNode*> children;
    int ending_words;
    int passing_through;

    explicit TrieNode(int occurrences = 0, int passing_through = 0) :
        ending_words(occurrences),
        passing_through(passing_through) {}
};

class Trie {
private:
    TrieNode* root = new TrieNode();

public:
    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;
    }

    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;
    }

    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;
    }

    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;
}