Cod sursa(job #2485137)

Utilizator Kln1000Ciobanu Bogdan Kln1000 Data 1 noiembrie 2019 00:52:44
Problema Trie Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.74 kb
#include <fstream>
#include <vector>
#include <string>

using namespace std;

#pragma pack(1)

class trie {
public:
    trie() {
        for (auto& i : root.sons)
            i = nullptr;
        root.parent = nullptr;
    }

    void add(std::string* target) {
        node* crawler = this->begin();

        for (auto letter : *target) {
            if (crawler->sons[normalize(letter)] == nullptr)
                ++(crawler->forks),
                crawler->sons[normalize(letter)] = new node(1 + crawler->level, normalize(letter)),
                crawler->sons[normalize(letter)]->parent = crawler;

            crawler = crawler->sons[normalize(letter)];
        }

        if (crawler->occurences++ == 0)
            crawler->end_of_word = true;
    }

    void remove(std::string* target) {
        node* crawler = this->begin();

        for (auto letter : *target) {
            if (crawler->sons[normalize(letter)] == nullptr)
                return;
            crawler = crawler->sons[normalize(letter)];
        }

        if (--crawler->occurences == 0) {
            crawler->end_of_word = false;
            node* next;

            while (crawler->forks == 0 && !crawler->end_of_word && crawler != this->begin()) {
                next = crawler->parent;
                --next->forks;
                next->sons[crawler->index] = nullptr;
                delete crawler;
                crawler = next;
            }
        }
    }

    int get_occurences(std::string* target) {
        node* crawler = this->begin();

        for (auto letter : *target) {
            if (crawler->sons[normalize(letter)] == nullptr)
                return 0;
            crawler = crawler->sons[normalize(letter)];
        }

        return crawler->occurences;
    }

    int get_closest_match_length(std::string* target) {
        node* crawler = this->begin();
        int retval = 0;

        for (auto letter : *target) {
            if (crawler->sons[normalize(letter)] == nullptr)
                return retval;
            ++retval;
            crawler = crawler->sons[normalize(letter)];
        }

        return retval;
    }

    ~trie() {
        return;
        for (auto i : root.sons)
            if (i != nullptr)
                clean_node(i);
    }

private:
    static const int start_of_alphabet = 'a';
    static const int size_of_alphabet = 26;

    int normalize(const char& target) {
        return target - start_of_alphabet;
    }

    struct node {
        node* sons[size_of_alphabet] = {};
        node* parent;
        int forks : 5,  /// delete bit fields for other alphabets
            level : 5,
            index : 6,
            occurences : 15,
            end_of_word : 1;
        node(int _level = 0, int letter = 0) : forks(0), occurences(0), end_of_word(false) {
            index = letter;
            level = _level;
        }
    } root;

    node* begin() {
        return &root;
    }

    void clean_node(node* target) {
        for (auto i : target->sons)
            if (i != nullptr)
                clean_node(i);

        delete target;
    }
};

int main() {
    ifstream fin("trie.in");
    ofstream fout("trie.out");
    int query;
    trie h;

    for (string str; fin >> query;) {
        fin >> str;
        switch (query) {
        case 0: {
            h.add(&str);
            break;
        }
        case 1: {
            h.remove(&str);
            break;
        }
        case 2: {
            fout << h.get_occurences(&str) << "\n";
            break;
        }
        case 3: {
            fout << h.get_closest_match_length(&str) << "\n";
            break;
        }
        }
    }
    return 0;
}