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;
}
發佈了53 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章