Cod sursa(job #804697)

Utilizator ChallengeMurtaza Alexandru Challenge Data 30 octombrie 2012 09:25:19
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.04 kb
#include <fstream>

using namespace std;

const char InFile[]="ahocorasick.in";
const char OutFile[]="ahocorasick.out";
const int MaxL=1000111;
const int MaxLen=10111;
const int MaxN=100;
const int MaxQSize=MaxLen*MaxN;
const int SIGMA=26;

struct TrieNode
{
	TrieNode()
	{
		for(register int i=0;i<SIGMA;++i)
		{
			son[i]=NULL;
		}
		next=NULL;
		count=0;
	}
	
	TrieNode *son[SIGMA],*next;
	int count;
};

ifstream fin(InFile);
ofstream fout(OutFile);

int N,Qst=0,Qsf=-1,index;
char S[MaxL],C[MaxLen],*ptr;
TrieNode *root,*Q[MaxQSize],*SOL[MaxN];

void TrieAdd(TrieNode *node)
{
	if(!(*ptr))
	{
		SOL[index]=node;
		return;
	}
	*ptr-='a';
	
	if(node->son[*ptr]==NULL)
	{
		node->son[*ptr]=new TrieNode;
	}
	++ptr;
	TrieAdd(node->son[*(ptr-1)]);
}

inline void QPush(TrieNode *nod)
{
	Q[++Qsf]=nod;
}

inline bool QNotEmpty()
{
	return Qst<=Qsf;
}

inline TrieNode* QPop()
{
	++Qst;
	return Q[Qst-1];
}

int main()
{
	root=new TrieNode();
	
	fin>>S;
	fin>>N;
	for(register int i=1;i<=N;++i)
	{
		fin>>C;
		ptr=C;
		index=i;
		TrieAdd(root);
	}
	fin.close();
	
	root->next=root;
	QPush(root);
	while(QNotEmpty())
	{
		TrieNode *node=QPop();
		
		for(register int i=0;i<SIGMA;++i)
		{
			if(node->son[i]==NULL)
			{
				continue;
			}
			
			TrieNode *suffix=node->next;
			while(suffix!=root && suffix->son[i]==NULL)
			{
				suffix=suffix->next;
			}
			
			if(suffix->son[i]!=NULL && suffix->son[i]!=node->son[i])
			{
				node->son[i]->next=suffix->son[i];
			}
			else
			{
				node->son[i]->next=root;
			}
			
			QPush(node->son[i]);
		}
	}
	
	TrieNode *node=root;
	ptr=S;
	while(*ptr)
	{
		int i=*ptr-'a';
		while(node!=root && node->son[i]==NULL)
		{
			node=node->next;
		}
		if(node->son[i]!=NULL)
		{
			node=node->son[i];
		}
		++node->count;
		++ptr;
	}
	
	for(register int i=Qsf;i>=0;--i)
	{
		Q[i]->next->count+=Q[i]->count;
	}
	
	for(register int i=1;i<=N;++i)
	{
		fout<<SOL[i]->count<<"\n";
	}
	fout.close();
	return 0;
}