hdu 3065 AC自动机

//    hdu 3065 AC自动机
//
//    题目大意:
//
//        给你n个短串,然后给你一个长串,问:各个短串在长串中,出现了多少次
//
//    解题思路:
//
//        AC自动机,插入,构建,查询就OK啦
//
//    感悟:
//
//        这道题真的是1A的哟~~~很开心~~~尽管是个裸地,继续加油哟~~~FIGHTING

#include 
#include 
#include 
#include 
#include 
using namespace std;

const int MAX_NODE = 200000;
const int SIGMA = 131;

struct Aho_Corasick{
    
    int ch[MAX_NODE][SIGMA];
    int f[MAX_NODE];
    int val[MAX_NODE];
    int last[MAX_NODE];
    int cnt[1008];
    int sz;

    void init(){
        sz = 1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
        val[0] = 0;
    }

    void insert(char *s, int v){
        int u = 0;
        int n = strlen(s);
        for (int i=0;i){
            int c = s[i];
            if (!ch[u][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
    }

    void getfail(){
        queue<int> que;
        for (int c = 0;c < SIGMA; c++){
            int u = ch[0][c];
            if(u){
                que.push(u);
                f[u] = 0;
                last[u] = 0;
            }
        }

        while(!que.empty()){
            int r = que.front();
            que.pop();

            for (int c = 0 ; c < SIGMA;c++){
                int u = ch[r][c];

                if (!u)
                    continue;

                que.push(u);

                int v = f[r];

                while( v && !ch[v][c])
                    v = f[v];
                
                f[u] = ch[v][c];

                last[u] = val[f[u]] ? f[u] : last[f[u]];
            }
        }
    }

    void get_cnt(int u){
        if (u){
            cnt[val[u]]++;
            get_cnt(last[u]);
        }
    }

    void query(char *s){
        int u = 0;
        
        int n = strlen(s);
        
        for(int i=0;i){
            int c = s[i];
            
            while(u && !ch[u][c])
                u = f[u];

            u = ch[u][c];

            if (val[u]){
                get_cnt(u);
            }else if (last[u]){
                get_cnt(last[u]);
            }
        }
    }



}ac;

int n;

char p[1008][52];

char str[2000008];

void input(){
    ac.init();
    char s[52];
    for (int i=1;i<=n;i++){
        scanf("%s",s);
        memcpy(p[i],s,sizeof(s));
        ac.insert(s,i);
    }
    ac.getfail();
    
    scanf("%s",str);

    ac.query(str);
    for (int i = 1;i<=n;i++){
        if (ac.cnt[i]){
            printf("%s: %d\n",p[i],ac.cnt[i]);
        }
    }
}

int main(){
    //freopen("1.txt","r",stdin);
    while(scanf("%d",&n)!=EOF){
        input();
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/KingJourney/p/4703400.html

你可能感兴趣的:(hdu 3065 AC自动机)