Cod sursa(job #1513040)

Utilizator fanache99Constantin-Buliga Stefan fanache99 Data 28 octombrie 2015 22:03:58
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.43 kb
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
char text[1000010],word[10010];
int answers[110],left,right;
struct trie{
    int matches;
    trie *sons[26],*fail;
    vector<int> strings;
    trie(){
        matches=0;
        fail=NULL;
        memset(sons,0,sizeof(sons));
    }
};
trie *root,*node_queue[10005*10005],*current;
void trie_insert(trie *node,char *letter,int index){
    if(*letter<'a'||*letter>'z'){
        node->strings.push_back(index);
        return;
    }
    if(node->sons[*letter-'a']==NULL)
        node->sons[*letter-'a']=new trie;
    trie_insert(node->sons[*letter-'a'],letter+1,index);
}
void bfs(){
    int letter;
    left=1;
    right=1;
    trie *node,*auxiliar;
    root->fail=root;
    node_queue[1]=root;
    while(left<=right){
        node=node_queue[left];
        for(letter=0;letter<26;letter++)
            if(node->sons[letter]!=NULL){
                auxiliar=node->fail;
                while(auxiliar!=root&&auxiliar->sons[letter]==NULL)
                    auxiliar=auxiliar->fail;
                if(auxiliar->sons[letter]!=NULL&&auxiliar->sons[letter]!=node->sons[letter])
                    auxiliar=auxiliar->sons[letter];
                node->sons[letter]->fail=auxiliar;
                right++;
                node_queue[right]=node->sons[letter];
            }
        left++;
    }
    root->fail=NULL;
}
void antibfs(){
    int i,j;
    trie *node;
    for(i=right;i>0;i--){
        node=node_queue[i];
        if(node->fail!=NULL)
            node->fail->matches+=node->matches;
        for(j=0;j<node->strings.size();j++)
            answers[node->strings[j]]=node->matches;
    }
}
int main(){
    freopen("ahocorasick.in","r",stdin);
    freopen("ahocorasick.out","w",stdout);
    int words,i,position,text_length;
    scanf("%s%d\n",&text,&words);
    text_length=strlen(text);
    root=new trie;
    for(i=1;i<=words;i++){
        scanf("%s",&word);
        trie_insert(root,word,i);
    }
    bfs();
    current=root;
    for(position=0;position<text_length;position++){
        while(current->sons[text[position]-'a']==NULL&&current!=root)
            current=current->fail;
        if(current->sons[text[position]-'a']!=NULL)
            current=current->sons[text[position]-'a'];
        current->matches++;
    }
    antibfs();
    for(i=1;i<=words;i++)
        printf("%d\n",answers[i]);
    return 0;
}