zoj3228AC自动机

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

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

#include 
#include 
#include 
#include 
#include 

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]; //每个词最后一次出现的地方。
queueq;

int insert(node* root,char *str,int flag)
{
    node *tmp=root;
    int l=strlen(str);
    for(int i=0;iint 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;
}

你可能感兴趣的:(kmp)