hdu2896(病毒侵袭)--AC自动机

过完年了,又回来集训。
年后第一题。
这道题写了一个晚上,可能太久没有写过了,有点生疏了。
最后还是请ztz大神来帮忙看了看。
总结:
1.AC自动机的数组是根据所输入模板的总字符来定。
2.对于tot=1,以及初始化的时候将它的儿子全指向自己都是必须的。
3.对于getans时不了解,就手动模拟。

纪念一下!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define Set(aa,bb) memset(aa,bb,sizeof(aa))
using namespace std;
const int maxn=100010;

struct Aho_corasick_automaton{
    int trie[maxn][130],fail[maxn],q[maxn],w[maxn],ans[maxn],_,tot,n,m;
    bool vis[maxn];
    char all[maxn];

    void init(){
        tot=1;
        For(i,0,128)trie[0][i]=1;
        Set(fail,0);
    }

    int newnode(){
        fail[++tot]=0;
        vis[tot]=0;
        For(i,0,127) trie[tot][i]=0;
        return tot;
    }

    void insert(char *s,int id){
        int len=strlen(s),p=1;
        For(i,0,len-1){
            int j=s[i];
            p=trie[p][j]?trie[p][j]:trie[p][j]=newnode();
        }
        w[p]=id;
        vis[p]=1;
    }

    void got(int now){
        For(i,0,127){
            int ls=trie[fail[now]][i];
            if(trie[now][i]) fail[trie[now][i]]=ls,vis[trie[now][i]]|=vis[ls];
            else trie[now][i]=ls;
        }
    }

    void getfail(){
        int f=0,l=1;
        q[1]=1;
        while(f<l){
            int top=q[++f];
            For(i,0,127){
                if(trie[top][i]) q[++l]=trie[top][i];
            }
            got(top);
        }
    }

    void getans(char *s){
        int len=strlen(s),p=1;
        For(i,0,len-1){
            int j=s[i];
            if(j>=33 && j<=126)
            {
                if(!trie[p][j])p=1;
                p=trie[p][j];
                if(!p)p=1;
            }
            else
            {
                p=1;
                continue;
            }
            for(int l=p;l>1;l=fail[l]){
                if(!vis[l])break;
                if(w[l]) ans[++_]=w[l];
            }
        }
    }

    void work(){
        init();
        scanf("%d%d",&n,&m);
        For(i,1,n){
            scanf("%s",all);
            insert(all,i);
        }
        getfail();
        scanf("%d",&m);
        int sum=0;
        For(i,1,m){
            scanf("%s",all);
            _=0;
            getans(all);
            if(!_) continue;
            sort(ans+1,ans+_+1);
            ++sum;
            printf("web %d: ",i);
            For(j,1,_-1) printf("%d ",ans[j]);
            printf("%d",ans[_]);
            puts("");
        }
        printf("total: %d",sum);
        puts("");
    }
}d;

int main(){
    d.work();
    return 0;
}
发布了51 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_35776579/article/details/54811435
今日推荐