Cod sursa(job #1606880)

Utilizator assa98Andrei Stanciu assa98 Data 20 februarie 2016 17:20:44
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.73 kb
#include <algorithm>
#include <vector>
#include <fstream>
#include <cstring>
#include <queue>
using namespace std;

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

const int SIGMA = 26;
const int MAX_N = 1000100;
const int MAX_L = 10100;
const int MAX_T = 110;

struct aho {

    aho *f[SIGMA], *fail;
    vector<int> cuv;
    int potriv; //how many times did this prefix appear in the query word
    
    void setFail(aho *_fail) {
        fail = _fail;
    }
    
    void getFail(aho *_fail, int poz) { //the whole building process is linear because every failEdge is accessed by O(number of sons)
        fail = _fail;
        while(fail != fail->fail && !fail->f[poz]) { //failEdge doesn't point to ROOT and failEdge doesn't point to valid node
            fail = fail->fail; 
        }
        if(fail->f[poz] && this != fail->f[poz]) {//failEdge points either to ROOT or to a valid node (different than THIS node)
            fail = fail->f[poz]; 
        }
    }
public:
    aho() {
        memset(f, 0, sizeof(f));
        fail = NULL;
        potriv = 0; 
    }

    void insert(char *c, int ind) { //basic trie insert
        if(*c == 0) {
            cuv.push_back(ind);
            return;
        }

        int v = *c - 'a';
        if(!f[v]) {
            f[v] = new aho();
        }
        f[v]->insert(c + 1, ind);
    }

    friend void getFailEdges();
    friend void pass(char*);  
    friend void leavesFirst();
};

aho *R = new aho();

vector<aho*> order;

void getFailEdges() {
    queue<aho*> Q;
    Q.push(R);
    order.push_back(R);
    R->setFail(R);
    while(!Q.empty()) {
        aho *nod = Q.front();
        Q.pop();
        for(int i = 0; i < SIGMA; i++) {
            if(nod->f[i]) {
                nod->f[i]->getFail(nod->fail, i);
                Q.push(nod->f[i]);
                order.push_back(nod->f[i]);
            }
        }
    }
    R->setFail(NULL);
}

void pass(char *c) {
    aho *nod = R;
    while(*c) {
        int v = *c - 'a';

        for(nod; !nod->f[v] && nod != R; nod = nod->fail);
        
        if(nod->f[v]) {
            nod = nod->f[v];
        }

        nod->potriv++;
        c++;
    }
}

int aparitii[MAX_T];

void leavesFirst() {
    for(int i = order.size() - 1; i >= 0; i--) {
        aho *nod = order[i];
        if(nod->fail) {
            nod->fail->potriv += nod->potriv;
        }
        for(auto it : nod->cuv) {
            aparitii[it] = nod->potriv;
        }
    }
}

char s[MAX_N];
char cuv[MAX_L];

int main() {
    fin >> s;
    int n;
    fin >> n;
    for(int i = 1; i <= n; i++) {
        fin >> cuv;
        R->insert(cuv, i);
    }
    getFailEdges();

    pass(s);
    leavesFirst();

    for(int i = 1; i <= n; i++) {
        fout << aparitii[i] << '\n';
    }

    return 0;
}