Cod sursa(job #2696587)

Utilizator AndreiD31Dragan Andrei AndreiD31 Data 16 ianuarie 2021 10:25:50
Problema Trie Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.07 kb
#include <bits/stdc++.h>

using namespace std;

ifstream f("trie.in");
ofstream g("trie.out");

struct trie
{
    int contor_prefix,contor_aparitii,next[26];
};
trie structura_initializare;
vector <trie> v;
int t,lungime_string;
char s[30];


/// dam update => stergem sau adaugam cuvant in trie
void update(int poz_trie,int poz_string, int val)
{
    v[poz_trie].contor_prefix += val; /// schimb(+1/-1) aparitia prefixului format pana la poz_string
    if(poz_string==lungime_string)
    {
        /// am ajuns la final
        /// in cazul acesta schimb(+1/-1) si numarul de apartii a intregului cuvant
        /// evident, nu mai continui mai departe
        v[poz_trie].contor_aparitii += val;
        return;
    }
    else
    {
        /// acum vreau sa merg mai departe
        int indice_urmator = int(s[poz_string]-'a');
        if(v[poz_trie].next[indice_urmator]==0)
        {
            /// daca 'spatiul' acesta inca nu este alocat in vectorul meu de trie v
            /// creez spatiul si il initializez cu "structura_initializare"
            v.push_back(structura_initializare);
            t++;
            v[poz_trie].next[indice_urmator]=t;
            /// t reprezinta numarul total de noduri alocate in trie-ul meu v
        }

        update(v[poz_trie].next[indice_urmator],poz_string+1,val);
    }
}

/// cerinta 1 - aflarea numarului de cuvinte complete
int query1()
{
    /// radacina vectorului de trie va fi "zero", adica acel nod tip "structura_initializare"
    int poz_trie=0,i;
    for(i=0;i<lungime_string;i++)
    {
        /// parcurg fiecare litera din sirul pe care il caut
        int indice_urmator=int(s[i]-'a');
        if(v[poz_trie].next[indice_urmator]==0)
        {
            /// daca nu am alocat spatiul, inseamna ca nu exista cuvantul pe care il caut
            /// adica nu i-am dat niciodata "update", implicit o initializare la spatiile de litere pe care sa le ocupe in trie
            break;
        }
        else
        {
            /// merg mai departe
            poz_trie=v[poz_trie].next[indice_urmator];
        }
    }

    if(i==lungime_string)
    {
        /// daca am ajuns pana la final, atunci inseamna ca exista acest cuvant
        return v[poz_trie].contor_aparitii;
    }
    else return 0;
}

/// cerinta 2 - aflarea celui mai lung prefix comun
int query2()
{
    /// aici pornesc de la radacina si iau fiecare caracter al cuvantului pana cand obtin frecventa prefixul <=0
    /// NOTA: daca cuvantul "lat" a fost pus in trie, iar eu caut cuvantul "lat" => lungimea este fix tot cuvantul, adica 3

    int poz_trie=0,i,poz_trie_urmator;
    for(i=0;i<lungime_string;i++)
    {
        int indice_urmator=int(s[i]-'a');
        if(v[poz_trie].next[indice_urmator]==0)
        {
            /// in cazul acesta este ca la query1 - adica nu am atribuit acel spatiu, deci nu pot sa merg mai departe
            break;
        }
        else
        {
            /// inseamna ca spatiul exista
            poz_trie_urmator = v[poz_trie].next[indice_urmator];
            if(v[poz_trie_urmator].contor_prefix<=0)
            {
                /// evident, daca din start am gasit o litera in prefix care apare de 0 sau mai putin de 0 ori atunci dau break
                /// nu mai merg mai departe, fiindca aici mi se termina prefixul
                break;
            }
            else
            {
                /// merg mai departe
                poz_trie=v[poz_trie].next[indice_urmator];
            }
        }
    }
    /// i va reprezenta de fapt lungimea maxima pana unde am mers
    /// i va incepe de la 0
    return i;
}

int tip;
int main()
{
    v.push_back(structura_initializare);
    /// radacina mea in vectorul trie va fi mereu un nod de tip "zero"
    /// evident t=0, initializat global

    while(f>>tip>>s)
    {
        lungime_string=strlen(s);

        if(tip==0)update(0,0,1);
        else if(tip==1)update(0,0,-1);
        else if(tip==2)g<<query1()<<'\n';
        else if(tip==3)g<<query2()<<'\n';
    }
    return 0;
}