Pagini recente » Cod sursa (job #541824) | Cod sursa (job #2676980) | Cod sursa (job #282760) | Cod sursa (job #1838667) | Cod sursa (job #1513786)
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
#define dim 1000005
#define dim2 10000*100 + 5 // Presupunand ca toate cuvintele sunt diferite
ifstream in("ahocorasick.in");
ofstream out("ahocorasick.out");
struct trie
{
trie *tata, *faillink;
trie *fiu[26];
int cnt,nrfii;
char lit; /// Litera adaugata ca sa ajung aici [0, 1, ... , 25]
trie()
{
int i;
cnt = 0;
nrfii = 0;
tata = this;
for(i=0; i<26; ++i) fiu[i] = NULL;
}
};
trie *vf = new trie;
trie *coada[dim2];
char text[dim];
int fcv[10005];
int cnt;
void add(char cuv[], int index_cuv)
{
int i,n;
trie *p, *next;
p = vf;
n = strlen(cuv);
for(i=0; i<n; ++i)
{
next = p->fiu[cuv[i] - 'a'];
if(next != NULL) p = next;
else
{
p->fiu[cuv[i]-'a'] = new trie;
p->fiu[cuv[i]-'a']->tata = p;
p->fiu[cuv[i]-'a']->lit = cuv[i]-'a';
p->nrfii += 1;
p = p->fiu[cuv[i]-'a'];
}
}
p->cnt = index_cuv;
}
int aparitii(char cuv[])
{
int i,n;
trie *p;
p = vf;
n = strlen(cuv);
i=0;
while(i<n && p!=NULL)
{
p = p->fiu[cuv[i] - 'a'];
++i;
}
if(p) return p->cnt;
else return 0;
}
void find_faillink(trie *p) /// A se apela numai pentru noduri de nivel 2 sau mai mic!
{
trie *i;
i = p->tata->faillink;
while(i->fiu[p->lit] == NULL && i!=vf)
{
i = i->faillink;
}
if(i->fiu[p->lit] == NULL) /// Am ajuns pana la vf si n-am gasit sufix (nici macar pe vf)
p->faillink = vf;
else /// Am gasit primul sufix (cel maxim)
p->faillink = i->fiu[p->lit];
}
void calc_solutii(trie *p)
{
trie *q;
q = p;
while(q!=vf) /// Daca am gasit o solutie, toate sufixele sunt si ele solutii
{
++fcv[q->cnt];
q = q->faillink;
}
}
int main()
{
char cuv[10005];
int n,i,j,m;
trie *p, *q;
in>>text;
in>>n;
for(i=1; i<=n; ++i)
{
in>>cuv;
//cout<<cuv<<"\n";
add(cuv,i);
//out<<aparitii(cuv)<<"\n";
}
/// Precalculez primele doua nivele
/// si creez o coada
cnt = 0;
vf->faillink = vf;
for(i=0; i<26; ++i)
if(vf->fiu[i] != NULL)
{
vf->fiu[i]->faillink = vf;
for(j=0; j<26; ++j)
if(vf->fiu[i]->fiu[j] != NULL)
{
++cnt;
coada[cnt] = vf->fiu[i]->fiu[j];
}
}
//cout<<"i=0 nod: "<<vf<<" tata: "<<vf->tata<<" faillink: "<<vf->faillink<<"\n\n";
//cout<<"i=a nod: "<<vf->fiu[0]<<" tata: "<<vf->fiu[0]->tata<<" faillink: "<<vf->fiu[0]->faillink<<" cnt="<<vf->fiu[0]->cnt<<"\n";
//cout<<"i=b nod: "<<vf->fiu[1]<<" tata: "<<vf->fiu[1]->tata<<" faillink: "<<vf->fiu[1]->faillink<<" cnt="<<vf->fiu[1]->cnt<<"\n";
//cout<<"i=c nod: "<<vf->fiu[2]<<" tata: "<<vf->fiu[2]->tata<<" faillink: "<<vf->fiu[2]->faillink<<" cnt="<<vf->fiu[2]->cnt<<"\n\n";
i=1;
while(i <= cnt)
{
find_faillink(coada[i]);
for(j=0; j<26; ++j)
if(coada[i]->fiu[j] != NULL)
{
++cnt;
coada[cnt] = coada[i]->fiu[j];
}
//cout<<"i="<<i<<" nod: "<<coada[i]<<" tata: "<<coada[i]->tata<<" faillink: "<<coada[i]->faillink<<" cnt="<<coada[i]->cnt<<"\n";
++i;
}
//cout<<"\n";
m = strlen(text);
p = vf;
for(i=0; i<m; ++i)
{
//cout<<"i="<<i<<"\n";
if(p->fiu[text[i] - 'a'] != NULL)
{
// As putea crea o functie avansez(), dar pentru doar doua instructiuni... nu merita
p = p->fiu[text[i] - 'a'];
calc_solutii(p);
}
else
{
while(p->fiu[text[i] - 'a'] == NULL && p!=vf) /// Caut primul sufix care ar putea continua cuvantul
{
p = p->faillink;
}
if(p->fiu[text[i] - 'a'] != NULL)
{
p = p->fiu[text[i] - 'a'];
calc_solutii(p);
}
// else raman pe loc
}
//for(j=1; j<=n; ++j) cout<<fcv[j]<<" "; cout<<"\n";
}
for(i=1; i<=n; ++i) out<<fcv[i]<<"\n";
return 0;
}