Cod sursa(job #2485130)

Utilizator Kln1000Ciobanu Bogdan Kln1000 Data 1 noiembrie 2019 00:45:50
Problema Trie Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.88 kb
#include <fstream>

using namespace std;

#pragma pack(1)

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

    void add(const char* target) {
        crawler = begin();
        offset = 0;

        for (char letter = *target; letter; letter = *(target + ++offset)) {
            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(const char* target) {
        crawler = begin();

        for (char letter = *target; letter; letter = *(target + ++offset)) {
            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(const char* target) {
        crawler = begin();

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

        return crawler->occurences;
    }

    int get_closest_match_length(const char* target) {
        crawler = begin();
        int retval = 0;

        for (char letter = *target; letter; letter = *(target + ++offset)) {
            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;
    static int8_t offset;

    inline 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, * crawler;

    node* begin() { return &root; }

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

        delete target;
    }
};

ifstream fin("trie.in");
ofstream fout("trie.out");

int main() {
    int query;
    trie h;
    char* str = new char[21];
    for (; 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;
        }
        }
    }
    delete[] str;
    return 0;
}