Cod sursa(job #2619583)

Utilizator andreisontea01Andrei Sontea andreisontea01 Data 28 mai 2020 00:31:02
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.07 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 105;

struct Trie{
    int cnt;
    vector<int> mtc;
    Trie *alfa[30], *suflink;
    Trie(){
        cnt = 0;
        for(int i = 0; i < 26; ++i) alfa[i] = NULL;
        suflink = NULL;
    }
} *root, *cursor, *coada[MAXN * MAXN];
int fr[MAXN];
int st, dr = 1;

void add(string str, int p){
    Trie *curent = root;
    for(auto c: str){
        int letter = c - 'a';
        if(curent->alfa[letter] == NULL) curent->alfa[letter] = new Trie();
        curent = curent->alfa[letter];
    }
    curent->mtc.push_back(p);
}

void genSufLinks(){
    coada[++st] = root;
    root->suflink = root;
    while(st <= dr){
        Trie *nod = coada[st++];
        for(int i = 0; i < 26; ++i){
            if(nod->alfa[i] == NULL) continue;
            Trie *suf = nod->suflink;
            while(suf != root && suf->alfa[i] == NULL) suf = suf->suflink;
            if(suf == root){
                if(suf->alfa[i] != NULL && suf->alfa[i] != nod->alfa[i]) nod->alfa[i]->suflink = suf->alfa[i];
                else nod->alfa[i]->suflink = root;
            }
            else nod->alfa[i]->suflink = suf->alfa[i];
            coada[++dr] = nod->alfa[i];
        }
    }
}

void scan(){
    for(int i = dr; i > 0; --i){
        Trie *nod = coada[i];
        if(nod->suflink != NULL) nod->suflink->cnt += nod->cnt;
        for(auto x: nod->mtc) fr[x] = nod->cnt;
    }
}

int main()
{
    ifstream fin("ahocorasick.in");
    ofstream fout("ahocorasick.out");
    string text;
    int n;
    fin >> text >> n;
    root = new Trie();
    for(int i = 1; i <= n; ++i){
        string word;
        fin >> word;
        add(word, i);
    }
    genSufLinks();
    cursor = root;
    for(auto c: text){
        int let = c - 'a';
        while(cursor != root && cursor->alfa[let] == NULL) cursor = cursor->suflink;
        if(cursor->alfa[let] != NULL) cursor = cursor->alfa[let];
        cursor->cnt++;
    }
    scan();
    for(int i = 1; i <= n; ++i) fout << fr[i] << "\n";
    return 0;
}