Cod sursa(job #2387035)

Utilizator alextodoranTodoran Alexandru Raul alextodoran Data 24 martie 2019 11:20:40
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.33 kb
#include <bits/stdc++.h>

using namespace std;

FILE* file = fopen("ahocorasick.in", "r");
ofstream fout ("ahocorasick.out");

const int L_MAX = 1000002;
const int N_MAX = 102;
const int BUFFER_SIZE = 4095;

struct Trie
{
    Trie* sons[26];
    int ap;
    Trie* maxPref;
    Trie* maxW;
    int lg;
    int apSubstr;
    Trie (int nlg)
    {
        for(int i = 0; i < 26; i++)
            sons[i] = NULL;
        ap = 0;
        maxPref = NULL;
        maxW = NULL;
        lg = nlg;
        apSubstr = 0;
    }
};

Trie* Root = new Trie(0);

void trieInsert (Trie* root, char* str)
{
    if(str[0] == '\0')
        root->ap++;
    else
    {
        if(root->sons[str[0] - 'a'] == NULL)
            root->sons[str[0] - 'a'] = new Trie(root->lg + 1);
        trieInsert(root->sons[str[0] - 'a'], str + 1);
    }
}

char a[L_MAX];
int n;
char w[N_MAX][L_MAX];

queue <Trie*> q;

void bfs ()
{
    Root->maxPref = Root->maxW = Root;
    q.push(Root);
    while(!q.empty())
    {
        Trie* root = q.front();
        q.pop();
        for(int i = 0; i < 26; i++)
            if(root->sons[i] != NULL)
            {
                root->sons[i]->maxPref = root->maxPref;
                while(root->sons[i]->maxPref != Root && root->sons[i]->maxPref->sons[i] == NULL)
                    root->sons[i]->maxPref = root->sons[i]->maxPref->maxPref;
                if(root->sons[i]->maxPref->sons[i] != NULL && root != Root)
                    root->sons[i]->maxPref = root->sons[i]->maxPref->sons[i];
                root->sons[i]->maxW = root->sons[i]->maxPref;
                if(root->sons[i]->maxW->ap == 0)
                    root->sons[i]->maxW = root->sons[i]->maxW->maxW;
                q.push(root->sons[i]);
            }
    }
}

void getFreq ()
{
    Trie* p = Root;
    int lga = strlen(a);
    for(int i = 0; i < lga; i++)
    {
        while(p != Root && p->sons[a[i] - 'a'] == NULL)
            p = p->maxPref;
        if(p->sons[a[i] - 'a'] != NULL)
            p = p->sons[a[i] - 'a'];
        if(p->ap > 0)
            p->apSubstr++;
        Trie* q = p->maxW;
        while(q != Root)
        {
            q->apSubstr++;
            q = q->maxW;
        }
    }
}

void printFreq (Trie* root, char *str)
{
    if(str[0] == '\0')
        fout << root->apSubstr << "\n";
    else
        printFreq(root->sons[str[0] - 'a'], str + 1);
}

char buffer[BUFFER_SIZE];
int pos = -1;

void read_buffer ()
{
    fread(buffer, sizeof(char), BUFFER_SIZE, file);
}

char read ()
{
    pos++;
    if(pos >= BUFFER_SIZE)
    {
        read_buffer();
        pos = 0;
    }
    return buffer[pos];
}

void read_int (int &x)
{
    char c;
    while(iswspace(c = read()));
    x = 0;
    while(isdigit(c))
    {
        x = x * 10 + c - '0';
        c = read();
    }
}

void read_str (char *str)
{
    char c;
    while(iswspace(c = read()));
    string s = "";
    while(c >= 'a' && c <= 'z')
    {
        s += c;
        c = read();
    }
    strcpy(str, s.c_str());
}

int main()
{
    read_buffer();
    read_str(a);
    read_int(n);
    for(int i = 1; i <= n; i++)
    {
        read_str(w[i]);
        trieInsert(Root, w[i]);
    }
    bfs();
    getFreq();
    for(int i = 1; i <= n; i++)
        printFreq(Root, w[i]);
    return 0;
}