Pagini recente » Autentificare | Cod sursa (job #1471567) | Istoria paginii runda/luca_oji3/clasament | Istoria paginii runda/asdfghjkl/clasament | Cod sursa (job #2707971)
#include<bits/stdc++.h>
using namespace std;
ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");
struct nod
{
vector<int> L;/// contine lista "literelor" pe care nu am "fail"
int ap;/// numar aparitii pentru fiecare nod
nod *S[26],*fail;/// link la succesori si fail
nod()/// constructor
{
L.resize(0);
ap=0;
for(int i=0;i<26;i++)
S[i]=NULL;
fail=NULL;
}
};
nod *root,*poz[101];
string P,W;
int n;
int main()
{
root = new nod;
f>>P>>n;
/// se construieste trie cu cele n cuvinte
for(int i=1;i<=n;i++)
{
f>>W;
nod *p=root;
for(auto it:W)
{
int k=it-'a';
if(!p->S[k])
{
p->S[k] = new nod;
p->L.push_back(k);
}
p=p->S[k];
}
/// se memoreaza pozitia unde se termina cuvantul in trie
poz[i]=p;
}
/// se construieste fail pentru fiecare nod de trie
vector<nod*>Q;
int nr=0,baza=0;
root->fail=root;/// pentru root fail=root
/// totii fii radacinii au fail=root
/// apoi toate nodurile se vor procesa nivel cu nivel
for(auto k:root->L)
{
root->S[k]->fail=root;
Q.push_back(root->S[k]);nr++;
}
while(baza<nr)
{
nod *X=Q[baza++];
for(auto k:X->L)
{
/// pentru fiecare fiu procesat setez fail !!!
/// plec de la fail-ul nodului curent
/// merg din fail in fail pana cand pot pleca dintr-unul
/// pe "litera" fiului procesat
/// daca nu merge ajung in radacina si fiul va avea fail in radacina
nod *failNow=X->fail;
do
{
if(failNow->S[k]){X->S[k]->fail=failNow->S[k];break;}
if(failNow==root){X->S[k]->fail=root;break;}
failNow=failNow->fail;
}
while(1);
/// dupa ce am setat fail la un fiu pun fiul in coada
/// mai tarziu voi seta fail pentru fiii acestuia !!!
Q.push_back(X->S[k]);nr++;
}
}
/// se parcurge textul (P) si ori de cate ori o litera "pleaca"
/// pe o directie buna merg acolo si cresc numarul de aparitii
/// Daca pe un nod de trie nu pot pleca pe litera ma mut in fail si
/// incerc de acolo.
int m=P.size();
nod *p=root;
for(int i=0;i<m;)
{
int k=P[i]-'a';
if(p->S[k])
{
p=p->S[k];
p->ap++;
i++;
}
else if(p==root)
i++;
else
p=p->fail;
}
for(;Q.size();Q.pop_back())
Q.back()->fail->ap+=Q.back()->ap;
for(int i=1;i<=n;i++)
g<<poz[i]->ap<<'\n';
}