Cod sursa(job #748910)

Utilizator scipianusFMI Ciprian Olariu scipianus Data 15 mai 2012 09:38:39
Problema Aho-Corasick Scor 25
Compilator cpp Status done
Runda Arhiva educationala Marime 1.95 kb
#include<fstream>
#include<cstring>
#include<vector>
#include<cmath>
#define ch *c-'a'
using namespace std;
int n,lvlmax;
char A[1000100],cuv[110][10100];
struct Trie
{
	int nr,c;
	Trie *fiu[26],*back,*tata;
	Trie(Trie *nod)
	{
		nr=0;
		c=0;
		tata=nod;
		memset(fiu,0,sizeof(fiu));
		back=NULL;
	}
};
Trie *T;
vector <Trie*> nivel[26];

inline void Insert(Trie *nod,char *c,int lvl)
{
	if(*c==0)
		return;
	if(nod->fiu[ch]==NULL)
	{
		nod->fiu[ch]=new Trie(nod);
		nod->fiu[ch]->c=ch;
		nivel[lvl+1].push_back(nod->fiu[ch]);
		lvlmax=max(lvlmax,lvl+1);
	}
	Insert(nod->fiu[ch],c+1,lvl+1);
}

inline void Citire()
{
	int i;
	ifstream fin("ahocorasick.in");
	fin>>A;
	fin>>n;
	T=new Trie(0);
	T->tata=0;
	for(i=1;i<=n;i++)
	{
		fin>>cuv[i];
		Insert(T,cuv[i],0);
	}
	fin.close();
}

inline void Construire_Muchii_De_Intoarcere()
{
	int i,j;
	Trie *nod;
	for(i=1;i<=lvlmax;i++)
	{
		for(j=0;j<nivel[i].size();j++)
		{
			nod=nivel[i][j]->tata->back;
			while(nod)
			{
				if(nod->fiu[nivel[i][j]->c])
				{
					nod=nod->fiu[nivel[i][j]->c];
					break;
				}
				nod=nod->back;
			}
			if(nod)
				nivel[i][j]->back=nod;
			else
				nivel[i][j]->back=T;
		}
	}
}

inline void Search(Trie *nod,char *c)
{
	if(*c==0)
		return;
	if(nod==NULL)
	{
		Search(T,c+1);
		return;
	}
	if(nod->fiu[ch])
	{
		nod->fiu[ch]->nr++;
		Search(nod->fiu[ch],c+1);
	}
	else
		Search(nod->back,c);
}

inline void Propaga()
{
	int i,j;
	for(i=lvlmax;i>0;i--)
		for(j=0;j<nivel[i].size();j++)
			nivel[i][j]->back->nr+=nivel[i][j]->nr;
}

inline int Query(Trie *nod,char *c)
{
	if(*c==0)
		return nod->nr;
	return Query(nod->fiu[ch],c+1);
}

inline void Afisare()
{
	int i;
	ofstream fout("ahocorasick.out");
	for(i=1;i<=n;i++)
		fout<<Query(T,cuv[i])<<"\n";
	fout.close();
}

int main()
{
	Citire();
	Construire_Muchii_De_Intoarcere();
	Search(T,A);
	Propaga();
	Afisare();
	return 0;
}