Cod sursa(job #3325546)

Utilizator Razvan23Razvan Mosanu Razvan23 Data 25 noiembrie 2025 18:43:37
Problema Hashuri Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.89 kb
#include <bits/stdc++.h>
using namespace std;

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

class Hash
{
public:
    int n; /// Am scos const pentru a putea atribui in constructor, sau il poti pune in lista de initializare
    vector<int> *H;         /// Hash Table pentru numere
    vector<string> *Hs;     /// Hash Table Stringuri
    vector<string> *Prefix; /// Hash Table Prefixe

    Hash(int _n = 666013)
    {
        this->n = _n;
        /// Alocam dinamic vectori
        H = new vector<int>[n + 5];
        Hs = new vector<string>[n + 5];
        Prefix = new vector<string>[n + 5];
    }

    ~Hash()
    {
        delete[] H;
        delete[] Hs;
        delete[] Prefix;
    }

    int Modulo(int x)
    {
        int res = x % n;
        if (res < 0) res += n; /// Tratare numere negative
        return res;
    }

    int Modulo_String(string x)
    {
        int i;
        long long p, nr;
        nr = 0;
        p = 1;
        for (i = 0; x[i] != 0; i++)
        {
            nr = (nr + (x[i] - 'a' + 1) * p) % n;
            p = (p * 137) % n;
        }
        return nr;
    }

    void Insert(int x)
    {
        int index = Modulo(x);
        /// Putem verifica daca exista deja pentru a evita duplicatele, dar e mai costisitor
        /// Pentru viteza maxima la insert, dam doar push_back
        H[index].push_back(x);
    }

    void Insert_String(string x)
    {
        int index = Modulo_String(x);
        Hs[index].push_back(x);
    }

    /// STERGE ELEMENT - Optimizat pentru Vector O(1)
    void Delete(int x)
    {
        int index = Modulo(x);
        /// Parcurgem vectorul bucket-ului
        const int lg = H[index].size();
        for (int i = 0; i < lg; i++)
        {
            if (H[index][i] == x)
            {
                /// 1. Copiem ultimul element peste cel pe care vrem sa il stergem
                H[index][i] = H[index].back();
                /// 2. Scoatem ultimul element (acum duplicat)
                H[index].pop_back();
                return; /// Ne oprim, am sters elementul
            }
        }
    }

    void Delete_String(string x)
    {
        int index = Modulo_String(x);
        const int lg = H[index].size();
        for (int i = 0; i < lg; i++)
        {
            if (Hs[index][i] == x)
            {
                Hs[index][i] = Hs[index].back();
                Hs[index].pop_back();
                return;
            }
        }
    }

    void Delete_Prefix(string x)
    {
        string s;
        int i;
        long long p, nr;
        nr = 0;
        p = 1;

        for (i = 0; x[i] != 0; i++)
        {
            /// Recalculam hash-ul pentru fiecare prefix
            nr = (nr + (x[i] - 'a' + 1) * p) % n;
            p = (p * 137) % n;
            s.push_back(x[i]);
            const int lg = Prefix[nr].size();
            /// Cautam prefixul 's' in bucket-ul 'nr'
            for(int j = 0; j < lg; j++)
                if(Prefix[nr][j] == s) /// Atentie: comparam cu 's' (prefixul curent), nu cu 'x' (tot cuvantul)
                {
                    Prefix[nr][j] = Prefix[nr].back();
                    Prefix[nr].pop_back();
                    break; /// Am gasit si sters prefixul curent, trecem la urmatorul prefix
                }
        }
    }

    void Afisare()
    {
        for (int i = 0; i < n; i++)
        {
            if (!H[i].empty())
            {
                cout << "Index " << i << ": ";
                for (int val : H[i]) /// Range-based for (mai curat)
                    cout << val << " ";
                cout << "\n";
            }
        }
    }

    bool Find(int x)
    {
        int index = Modulo(x);
        /// Parcurgere specifica vector (index sau range-based)
        for (int val : H[index])
            if (val == x) return true;
        return false;
    }

    bool Find_String(string x)
    {
        int index = Modulo_String(x);
        for (const string &s : Hs[index]) /// Folosim const string& pentru a evita copierea stringului la fiecare pas
            if (s == x) return true;
        return false;
    }

    bool Find_Prefix(string x)
    {
        int index = Modulo_String(x);
        for (const string &s : Prefix[index])
            if (s == x) return true;
        return false;
    }

    virtual void Add_Prefix(string x)
    {
        string s;
        int i;
        long long p, nr;
        nr = 0;
        p = 1;
        for (i = 0; x[i] != 0; i++)
        {
            nr = (nr + (x[i] - 'a' + 1) * p) % n;
            p = (p * 137) % n;
            s.push_back(x[i]);
            Prefix[nr].push_back(s);
        }
    }

    void Find_Longest_Prefix(string x)
    {
        string s, aux;
        int i, lg;
        long long p, nr;
        nr = lg = 0;
        p = 1;
        aux = x;
        /// Aici logica pare a fi: daca nu gasim prefixe, returnam stringul initial?
        /// Am lasat logica ta originala.

        for (i = 0; x[i] != 0; i++)
        {
            nr = (nr + (x[i] - 'a' + 1) * p) % n;
            p = (p * 137) % n;
            s.push_back(x[i]);
            if (!Prefix[nr].empty() && Find_Prefix(s))
            {
                lg = i + 1;
                aux = s;
            }
        }
        cout << aux << " ";
    }
};

class Hashuri : public Hash
{
public:
    Hashuri(int _n = 123457) : Hash(_n)
    { }
    void Rezolvare()
    {
        int op, n, i, x;
        fin >> n;
        for(i=1; i<=n; i++)
        {
            fin >> op >> x;
            if(op == 1) Insert(x);
            else if(op == 2) Delete(x);
            else fout << Find(x)  << "\n";
        }
    }
};

int main()
{
    ios_base::sync_with_stdio(0);
    fin.tie(0);
    fout.tie(0);
    Hashuri A;
    A.Rezolvare();
    fin.close();
    fout.close();
    return 0;
}