您的位置:首页 > 其它

ZOJ 3228 AC自动机 重叠和不重叠

2017-02-28 17:19 369 查看
点击打开链接

题意:给定模式串,问下面的串最多出现多少次,0代表可以重叠,1代表不能重叠

思路:正常的0可以用模版直接实现,1的可以再写一个查询的,不能重叠,尽量先取前面,结果是最优的,所以我就记录这个串上一次出现的位置,然后在走了串这么长的长度才可以在+1.

[html] view
plain copy

#include <stdio.h>  

#include <string.h>  

#include <memory.h>  

struct node{  

    node *fail;  

    node *next[26];  

    int id;  

    node(){  

        fail=NULL;  

        id=0;  

        memset(next,NULL,sizeof(next));  

    }  

}*q[100000],*root;  

char str1[100003][7],str2[100003];  

int A[100003],cnt[100003][2],pos[100003],Len[100003],n;  

void insert_Trie(char *str,int num1){  

    node *p=root;  

    int i=0,id;  

    while(str[i]){  

        id=str[i]-'a';  

        if(p->next[id]==NULL) p->next[id]=new node();  

        p=p->next[id];i++;  

    }  

    p->id=num1;  

}  

int search_1(char *str){  

    node *p=root;  

    int m,i=0;  

    while(str[i]){  

        m=str[i]-'a';  

        if(p->next[m]==NULL) return -1;  

        p=p->next[m];  

        i++;  

    }  

    return p->id;  

}  

void build_ac(){  

    int head=0,tail=0;  

    root->fail=NULL;  

    q[head++]=root;  

    node *p,*temp;  

    while(head!=tail){  

        temp=q[tail++];  

        tail%=100000;  

        for(int i=0;i<26;i++){  

            if(temp->next[i]!=NULL){  

                if(temp==root) temp->next[i]->fail=root;  

                else{  

                    p=temp->fail;  

                    while(p!=NULL){  

                        if(p->next[i]!=NULL){  

                            temp->next[i]->fail=p->next[i];  

                            break;  

                        }  

                        p=p->fail;  

                    }  

                    if(p==NULL) temp->next[i]->fail=root;  

                }  

                q[head++]=temp->next[i];  

                head%=100000;  

            }  

        }  

    }  

}  

void query(){  

    int i=0;  

    node *p=root,*temp;  

    while(str2[i]){  

        int id=str2[i]-'a';  

        while(p->next[id]==NULL&&p!=root) p=p->fail;  

        p=p->next[id];  

        p=(p==NULL)?root:p;  

        temp=p;  

        while(temp!=root){  

            if(temp->id){  

                cnt[temp->id][0]++;  

            }  

            temp=temp->fail;  

        }  

        i++;  

    }  

}  

void query1(){  

    int i=0;  

    node *p=root,*temp;  

    while(str2[i]){  

        int id=str2[i]-'a';  

        while(p->next[id]==NULL&&p!=root) p=p->fail;  

        p=p->next[id];  

        p=(p==NULL)?root:p;  

        temp=p;  

        while(temp!=root){  

            if(temp->id&&i-pos[temp->id]>=Len[temp->id]){  

                pos[temp->id]=i;  

                cnt[temp->id][1]++;  

            }  

            temp=temp->fail;  

        }  

        i++;  

    }  

}  

int query_num(char *str,int aa){  

    int i=0;  

    node *p=root;  

    while(str[i]){  

        int id=str[i]-'a';  

        p=p->next[id];  

        i++;  

    }  

    return cnt[p->id][aa];  

}  

void del(node *p){  

     if(p==NULL)return ;  

     for(int i=0;i<26;i++)del(p->next[i]);  

     delete p;  

}  

int main(){  

    int t=1;  

    while(scanf("%s",str2)!=-1){  

        scanf("%d",&n);  

        root=new node();  

        memset(cnt,0,sizeof(cnt));  

        memset(pos,-1,sizeof(pos));  

        for(int i=1;i<=n;i++){  

            scanf("%d%s",&A[i],str1[i]);  

            Len[i]=strlen(str1[i]);  

            insert_Trie(str1[i],i);  

        }  

        build_ac();  

        query();  

        query1();  

        printf("Case %d\n",t++);  

        for(int i=1;i<=n;i++){  

            int ttt=query_num(str1[i],A[i]);  

            printf("%d\n",ttt);  

        }  

        printf("\n");  

        del(root);  

    }  

    return 0;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AC自动机