Cod sursa(job #804535)

Utilizator vlad.doruIon Vlad-Doru vlad.doru Data 29 octombrie 2012 22:06:28
Problema Aho-Corasick Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 3.24 kb
#include <fstream>
#include <string>
#include <queue>
#include <iostream>

using namespace std;

ifstream in("ahocorasick.in");
ofstream out("ahocorasick.out");

int const ALF_SIZE=30;

int aparitii[11000];

class node;
 vector < node* > ordbf;

 class node{
	bool final;
	int appereances;
	int wordnr;
	node *link[ALF_SIZE];
	node *pref;
	node *nextDictWord;
public:
	node(){
		int i;
		for(i=0;i<ALF_SIZE;++i){
			this->link[i]=NULL;
		}
		this->pref=NULL;
		this->final=false;
		this->nextDictWord=NULL;
		this->appereances=0;
	}
	node* linknode(char x){
		if(link[x-'a']){
			return link[x-'a'];
		}
		link[x-'a']=new node();
		return link[x-'a'];
	}
	bool setfinal(int x){
		final=true;
		wordnr=x;
		return true;
	}
	bool isfinal(){
		return final;
	}
	bool ahoCorasick(){
		int i;
		queue<node *> coada;
		for(i=0;i<ALF_SIZE;++i){
			if(link[i]){
				coada.push(link[i]);
				ordbf.push_back(link[i]);
				link[i]->pref=this;
			}
		}
		node *tata,*fiu,*aux;
		while(!coada.empty()){
			tata=coada.front();
			coada.pop();
			for(i=0;i<ALF_SIZE;++i){
				if(tata->link[i]){
					fiu=tata->link[i];
					aux=tata->pref;
					coada.push(fiu);
					ordbf.push_back(fiu);
					while(aux!=NULL){
						if(aux->link[i]){
							fiu->pref=aux->link[i];
							break;
						}
						aux=aux->pref;
					}
					if(aux==NULL){
						fiu->pref=this;
					}
					aux=fiu->pref;
					while(aux!=NULL){
						if(aux->isfinal()){
							fiu->nextDictWord=aux;
							break;
						}
						aux=aux->pref;
					}
				}
			}
		}
		return true;
	}
	void parse(string s){
        node * currentnode=this;
        string::iterator it;
        for(it=s.begin();it<s.end();++it){
            while(currentnode->link[*it-'a']==NULL && currentnode!=this){
                currentnode=currentnode->pref;
            }
            if(currentnode->link[*it-'a']){
                currentnode=currentnode->link[*it-'a'];
                currentnode->appereances++;
            }
        }
	}
	void update_appereances(){
        int i;
        node *curent;
        for(i=ordbf.size()-1;i>=0;--i){
            curent=ordbf[i];
            if(curent->nextDictWord!=this && curent->nextDictWord){
               curent->nextDictWord->appereances+=curent->appereances;
            }
            if(!curent->isfinal())
                continue;
            aparitii[curent->wordnr]=curent->appereances;
        }
	}
};


class automata{
	node *root;
public:
	automata(){
		root=new node();
	}
	bool add(string s,int wordnr){
		node *currentnode=root;
		root->setfinal(0);
		string:: iterator it;
		for(it=s.begin();it<s.end();++it){
			currentnode=currentnode->linknode(*it);
		}
		currentnode->setfinal(wordnr);
	}
	bool constructautomata(){
		return root->ahoCorasick();
	}
	void search(string s){
        root->parse(s);
        root->update_appereances();
	}
};

int main(){
	automata AhoCorasick;
	string sir,cuvant;
	int i;
	int nrcuvinte;
	in>>sir;
	in>>nrcuvinte;
	for(i=1;i<=nrcuvinte;++i){
		in>>cuvant;
		AhoCorasick.add(cuvant,i);
	}
	AhoCorasick.constructautomata();
	AhoCorasick.search(sir);
	for(i=1;i<=nrcuvinte;++i){
        out<<aparitii[i]<<"\n";
	}
	return 0;
}