Cod sursa(job #2332658)

Utilizator circeanubogdanCirceanu Bogdan circeanubogdan Data 30 ianuarie 2019 22:36:43
Problema Aho-Corasick Scor 100
Compilator cpp-32 Status done
Runda Arhiva educationala Marime 2.31 kb
#include <fstream>
#include <vector>
#include <deque>
#include <cstring>
#define DIMTEXT 1000002
#define DIMWORD 10002
#define NRDIM 102

using namespace std;

ifstream in ("ahocorasick.in");
ofstream out("ahocorasick.out");

int n;

char text[DIMTEXT];

char words[NRDIM][DIMWORD];

struct node{
    int sol;
    vector<node*> sons;
    node* back;
    node* letters[26];
    node(){
        for(int i = 0; i < 26; ++ i)
            letters[i] = NULL;
        back = NULL;
        sol = 0;
    }
};

node* reference[DIMWORD];

node* root;

deque<node*> q;

node* add(node* nodeCurr, char* c){
    if(*c == 0)
        return nodeCurr;
    if(nodeCurr->letters[*c - 'a'] == NULL)
        nodeCurr->letters[*c - 'a'] = new node;
    return add(nodeCurr->letters[*c - 'a'], c + 1);
}

void dfs(node* currentNode){
    for(auto it : currentNode->sons){
        dfs(it);
        currentNode->sol += it->sol;
    }
}

int main()
{
    in>>(text)>>n;
    root = new node;
    for(int i = 1; i <= n; ++ i){
        in>>(words[i]);
        reference[i] = add(root, words[i]);
        
    }
    
    q.push_back(root);
    
    while(!q.empty()){
        node* currentNode = q.front();
        q.pop_front();
        for(int i = 0; i < 26; ++ i){
            if(currentNode->letters[i] == NULL)
                continue;
            node* last = currentNode->back;
            while(last != NULL && last->letters[i] == NULL)
                last = last->back;
            
            if(last == NULL)
                currentNode->letters[i]->back = root;
            else
                currentNode->letters[i]->back = last->letters[i];
            
            currentNode->letters[i]->back->sons.push_back(currentNode->letters[i]);
            q.push_back(currentNode->letters[i]);
        }
    }
    
    int sizeText = strlen(text);
    
    node* last = root;
    
    for(int i = 0; i < sizeText; ++ i){
        while(last != NULL && last->letters[text[i] - 'a'] == NULL)
            last = last->back;
        
        if(last == NULL)
            last = root;
        
        if(last->letters[text[i] - 'a'] != NULL){
            last->letters[text[i] - 'a']->sol ++;
            last = last->letters[text[i] - 'a'];
        }
        
    }
    
    dfs(root);
    
    for(int i = 1; i <= n; ++ i){
        out<<reference[i]->sol<<'\n';
    }
    
    return 0;
}