【ZOJ3228】白濑肆の完美算法教室补番作,0.7%达成 白濑肆×AC自动机

来源:互联网 发布:快走丝线切割直线编程 编辑:程序博客网 时间:2024/06/05 16:49
#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <queue>using namespace std;/**    就是一个AC自动机    但是每个单词有两个状态,[0]是可以overlap,[1]是不能overlap时候的次数    我们用last数组记录下每个不能overlap的单词出现的位置,如果    当前位置 - last[word] + 1 > strlen(word),那么证明该单词并未overlap,更新last数组,对应次数+1即可    补番作,水题。*/const int MAX_ALPHABET = 27;const int MAX_TEXT = 100010;const int MAX_WORD = 7;const int MAX_WORD_NUM = 100010;struct node{    int id;    int cnt;    int len;    node* fail;    node* next[MAX_ALPHABET];    node()    {        id = -1; //指定该单词出现的位置。        cnt = 0;        fail = NULL;        len = 0;        memset(next,0,sizeof(next));    }};int cnt;int loc[MAX_WORD_NUM];int type[MAX_WORD_NUM];int strcnt[MAX_WORD_NUM][2]; // 每个词儿两个状态int last[MAX_WORD_NUM]; //每个词最后一次出现的地方。queue<node*> q;////变量区结束///int AC_insert(node* root,char* dest,int flag){    node* tmp = root;    int l = strlen(dest);    for(int i = 0 ; i < l ; i++)    {        int k = dest[i]-'a';        if( tmp->next[k] == NULL )        {            tmp->next[k] = new node();        }        tmp = tmp->next[k];    }    if( tmp->id == -1)    {        tmp->id = cnt;        cnt++;    }    tmp->cnt = tmp->cnt | flag;    tmp->len = l;    return tmp->id;  //标明该单词在单词列表中第几个出现。。。}void AC_build(node* root){    root->fail = NULL;    q.push(root);    while(!q.empty())    {        node* tmp = q.front();        q.pop();        node *p;        for(int i = 0 ; i < 26 ; i++)        {            if(tmp->next[i])            {                if( tmp == root )                {                    tmp->next[i]->fail = root;                }                else                {                    p = tmp->fail;                    while(p)                    {                        if( p->next[i] )                        {                            tmp->next[i]->fail = p->next[i];                            break;                        }                        p = p->fail;                    }                    if( !p )                        tmp->next[i]->fail = root;                }                q.push(tmp->next[i]);            }        }    }}void AC_search(node* root,char* dest){    node* tmp;    node* p;    p = root;    for(int i = 0 ; dest[i] ; i++)    {        int ind = dest[i] - 'a';        while( p->next[ind]==NULL && p != root)            p = p->fail;        p = p->next[ind];        if( p == NULL )            p = root;        tmp = p;        while( tmp != NULL )        {            if( tmp->id != -1 )            {                if( tmp->cnt & 1 )                {                    strcnt[tmp->id][0]++;                }                if( tmp->cnt & 2 )                {                    if( i - tmp->len + 1 > last[tmp->id] )                    {                        strcnt[tmp->id][1]++;                        last[tmp->id] = i;                    }                }            }            tmp = tmp->fail;        }    }}int main(){#ifndef ONLINE_JUDGE    freopen("B:\\acm\\SummerVacation\\String-I\\B.in","r",stdin);    freopen("B:\\acm\\SummerVacation\\String-I\\B.out","w",stdout);#endif    char dest[MAX_TEXT];    char word[MAX_WORD];    int t = 1;    while(scanf("%s",dest) != EOF)    {        memset(last,-1,sizeof(last));        memset(strcnt,0,sizeof(strcnt));        cnt = 1;        node* root = new node();        int N;        scanf("%d",&N);        for(int i = 0 ; i < N ; i++)        {            scanf("%d %s",&type[i],word);            loc[i] = AC_insert(root,word,type[i]+1);        }        AC_build(root);        AC_search(root,dest);        printf("Case %d\n",t++);        int ans;        for(int i = 0 ; i < N ; i++)        {            ans = strcnt[loc[i]][type[i]];            printf("%d\n",ans);        }        printf("\n");    }#ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);#endif    return 0;}


	
				
		
原创粉丝点击