Pagini recente » Istoria paginii runda/alexei2/clasament | Cod sursa (job #904564) | Cod sursa (job #2054556) | Rating Filea Razvan (Razvan145) | Cod sursa (job #2006007)
#include <iostream>
#include <fstream>
#include <string.h>
#include <queue>
#include <vector>
using namespace std;
int n, pos=1;
char A [1000005];
char B [10005];
int ans [105];
class nod {
public:
nod * fail, * sons[26], *parent;
int eterminal, cnt;
char c;
nod()
{
memset(sons, 0, sizeof(sons));
fail = NULL;
eterminal =0;
cnt =0;
}
};
nod T;
vector <nod *> Q;
queue <nod *> Q2;
void ins(char * c, nod * curr)
{
//cout<<"INSEREZ FIUL "<<c[0]<<" LA NODUL "<<curr<<" ("<<curr->c<<")\n";
int fiu = (int)(c[0]-'a');
if(c[0]==0) //caracter nul
{
curr->eterminal=pos;
++pos;
}
if('a'<=c[0] && c[0]<='z')
{
if(curr->sons[fiu]==NULL) //daca nu am mai avut fiul asta
curr->sons[fiu]=new nod;
curr->sons[fiu]->c=c[0];
ins(c+1, curr->sons[fiu]);
}
}
void befeu (nod * d)
{
//Q.resize(256);
nod * fail;
//Q.push(d);
for(int i=0;i<26;++i)
if(d->sons[i]!=NULL) //avem muchie cu litera respectiva
{
d->sons[i]->parent=d->fail;
Q.push_back(d->sons[i]);
}
//while(!Q.empty())
for(int j=0;j<Q.size();++j)
{
//d=Q.front();
d=Q[j];
//Q.pop();
//++j;
if (d==&T)
continue;
fail = d->parent; //luam failu parintelui (cam ca la kmp)
while(fail->sons[d->c-'a']==NULL && fail != &T) //calculam fail function cam ca la KMP
{
fail=fail->fail;
}
d->fail = fail->sons[d->c-'a'];
if(d->fail == NULL)
d->fail = &T;
if(d->fail == d)
d->fail = &T;
//cout<<"NODUL "<<d<<"("<<d->c<<") "<<" ARE FAIL "<<d->fail<<" ("<<d->fail->c<<")\n";
for(int i=0;i<26;++i)
{
if(d->sons[i]!=NULL) //avem muchie cu litera respectiva
{
d->sons[i]->parent=d->fail;
Q.push_back(d->sons[i]);
}
}
}
}
void befeu_special_doar_pt_infoarena()
{
for(int i=Q.size()-1;i>=0;--i)
{
if(Q[i]->fail!=&T)
Q[i]->fail->cnt+=Q[i]->cnt;
}
nod * d;
Q2.push(&T);
while(!Q2.empty())
{
d=Q2.front();
if(d->eterminal>0)
ans[d->eterminal]=d->cnt;
Q2.pop();
for(int i=0;i<26;++i)
{
if(d->sons[i]!=NULL)
Q2.push(d->sons[i]);
}
}
}
int main()
{
ifstream in ("ahocorasick.in");
ofstream out ("ahocorasick.out");
in>>A;
in>>n;
T.fail = &T;
T.parent = &T;
for(int i=0;i<n;++i)
{
in>>B;
ins(B, &T);
}
befeu(&T);
nod *curr = &T;
int lg = strlen(A);
for(int i=0;i<lg;++i)
{
while(curr->sons[A[i]-'a']==NULL && curr!=&T)
{
curr=curr->fail;
//if(curr->eterminal>0) //trebe sa pun si daca NU mergem in fail sa se actualizeze
//curr->cnt++;
}
if(curr->sons[A[i]-'a']!=NULL)
{
//if(curr->fail->eterminal>0)
//curr->fail->cnt++;
curr=curr->sons[A[i]-'a'];
}
//if(curr->eterminal>0) //e o idee buna sa incrementezi la toate nodurile ca oricum le parcurgi si ADD consuma mai putin decat JG
curr->cnt++;
}
befeu_special_doar_pt_infoarena();
for(int i=1;i<=n;++i)
out<<ans[i]<<"\n";
return 0;
}