Cod sursa(job #804517)

Utilizator vlad.doruIon Vlad-Doru vlad.doru Data 29 octombrie 2012 21:49:30
Problema Aho-Corasick Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.99 kb
#include <fstream>
#include <string>
#include <queue>
#include <iostream>

using namespace std;

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

int const ALF_SIZE=35;

string cuvinte[11000];
int aparitii[11000];

class node;

vector < node* > ordbf;

class node{
	bool final;
	int appereances;
	vector<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.push_back(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 df(){
        int i;
        /*for(i=0;i<ordbf.size();i++){
            if(!ordbf[i]->isfinal()){
                continue;
            }
            for(int j=0;j<ordbf[i]->wordnr.size();++j){
                out<<cuvinte[ordbf[i]->wordnr[j]]<<":"<<ordbf[i]->appereances<<"\n";
            }
        }*/

        for(i=ordbf.size()-1;i>=0;i--){
            if(ordbf[i]->nextDictWord!=this && ordbf[i]->nextDictWord){
               ordbf[i]->nextDictWord->appereances+=ordbf[i]->appereances;
               /* if(ordbf[i]->nextDictWord->isfinal()){
                    for(int j=0;j<ordbf[i]->wordnr.size();++j){
                    aparitii[ordbf[i]->nextDictWord->wordnr[j]]+=ordbf[i]->appereances;
                    }
                }*/
            }
            for(int j=0;j<ordbf[i]->wordnr.size();++j){
                aparitii[ordbf[i]->wordnr[j]]=ordbf[i]->appereances;
           //out<<cuvinte[ordbf[i]->wordnr[j]]<<":"<<ordbf[i]->appereances<<"\n";
            }
        }
            /*if(ordbf[i]->pref){
                ordbf[i]->pref->appereances+=ordbf[i]->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->df();
	}
};

int main(){
	automata AhoCorasick;
	string sir,cuvant;
	int i;
	int nrcuvinte;

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