zoj3228AC自动机

来源:互联网 发布:hbase不直接删除数据 编辑:程序博客网 时间:2024/05/01 09:31

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110773#problem/D

0状态时就是模板,1时判断一下后匹配的位置减前面的距离是不是大于当前单词的距离

#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <queue>using namespace std;const int MAX=100010;struct node{    int id;    int cnt;    int len;    node* fail;    node* next[27];    node()    {        id=-1;        cnt=0;        fail=NULL;        len=0;        memset(next,0,sizeof(next));    }};int cnt;int loc[MAX];int type[MAX];int strcnt[MAX][2]; // 每个词两个状态int last[MAX]; //每个词最后一次出现的地方。queue<node*>q;int insert(node* root,char *str,int flag){    node *tmp=root;    int l=strlen(str);    for(int i=0;i<l;i++)    {        int p=str[i]-'a';        if(tmp->next[p]==NULL)tmp->next[p]=new node();        tmp=tmp->next[p];    }    if(tmp->id==-1)    {        tmp->id=cnt;        cnt++;    }    tmp->cnt=tmp->cnt|flag;    tmp->len=l;    return tmp->id;}void build_ac(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 query(node* root,char* str){    node* tmp;    node* p;    p=root;    for(int i=0;str[i];i++)    {        int ind=str[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;        }    }}void free_(node *r){    for(int i=0;i<26;i++)    {        if(r->next[i])        free_(r->next[i]);    }    free(r);}int main(){    char str[100010];    char word[10];    int t=1;    while(scanf("%s",str) != 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] = insert(root,word,type[i]+1);        }        build_ac(root);        query(root,str);        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");        free_(root);    }    return 0;}
0 0