HDU 3065 病毒侵袭持续中(AC自动机 模板)题解

时间:2021-12-28 12:38:44

题意:给出主串中每个模式串的个数

思路:毒瘤出题人多组数据没说给的是多组数据。

板子:

struct Aho{
    struct state{
        int next[130];
        int fail, cnt;
    }node[maxn];
    int size;
    queue<int> q;

    void init(){
        size = 0;
        newtrie();
        while(!q.empty()) q.pop();
    }

    int newtrie(){
        memset(node[size].next, 0, sizeof(node[size].next));
        node[size].cnt = node[size].fail = 0;
        return size++;
    }

    void insert(char *s, int id){
        int len = strlen(s);
        int now = 0;
        for(int i = 0; i < len; i++){
            int c = s[i];
            if(node[now].next[c] == 0){
                node[now].next[c] = newtrie();
            }
            now = node[now].next[c];
        }
        node[now].cnt = id;
    }

    void build(){
        node[0].fail = -1;
        q.push(0);

        while(!q.empty()){
            int u = q.front();
            q.pop();
            for(int i = 0; i < 130; i++){
                if(node[u].next[i]){
                    if(u == 0) node[node[u].next[i]].fail = 0;
                    else{
                        int v = node[u].fail;
                        while(v != -1){
                            if(node[v].next[i]){
                                node[node[u].next[i]].fail = node[v].next[i];
                                break;
                            }
                            v = node[v].fail;
                        }
                        if(v == -1) node[node[u].next[i]].fail = 0;
                    }
                    q.push(node[u].next[i]);
                }
            }
        }
    }

    void get(int u){ //匹配规则
        while(u){
            if(node[u].cnt) ans[node[u].cnt]++;
            u = node[u].fail;
        }
    }

    void match(char *s){
        int ret = 0, now = 0;
        int len = strlen(s);
        for(int i = 0; i < len; i++){
            int c = s[i];
            if(node[now].next[c]){
                now = node[now].next[c];
            }
            else{
                int p = node[now].fail;
                while(p != -1 && node[p].next[c] == 0){
                    p = node[p].fail;
                }
                if(p == -1) now = 0;
                else now = node[p].next[c];
            }
            get(now);    //视情况自己定
        }
    }
}ac;

 

代码:

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 50000 + 10;
const int maxM = 2000000 + 10;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e4 + 7;

char s[maxM];
char b[1001][51];
int ans[1001];
struct Aho{
    struct state{
        int next[130];
        int fail, cnt;
    }node[maxn];
    int size;
    queue<int> q;

    void init(){
        size = 0;
        newtrie();
        while(!q.empty()) q.pop();
    }

    int newtrie(){
        memset(node[size].next, 0, sizeof(node[size].next));
        node[size].cnt = node[size].fail = 0;
        return size++;
    }

    void insert(char *s, int id){
        int len = strlen(s);
        int now = 0;
        for(int i = 0; i < len; i++){
            int c = s[i];
            if(node[now].next[c] == 0){
                node[now].next[c] = newtrie();
            }
            now = node[now].next[c];
        }
        node[now].cnt = id;
    }

    void build(){
        node[0].fail = -1;
        q.push(0);

        while(!q.empty()){
            int u = q.front();
            q.pop();
            for(int i = 0; i < 130; i++){
                if(node[u].next[i]){
                    if(u == 0) node[node[u].next[i]].fail = 0;
                    else{
                        int v = node[u].fail;
                        while(v != -1){
                            if(node[v].next[i]){
                                node[node[u].next[i]].fail = node[v].next[i];
                                break;
                            }
                            v = node[v].fail;
                        }
                        if(v == -1) node[node[u].next[i]].fail = 0;
                    }
                    q.push(node[u].next[i]);
                }
            }
        }
    }

    void get(int u){ //匹配规则
        while(u){
            if(node[u].cnt) ans[node[u].cnt]++;
            u = node[u].fail;
        }
    }

    void match(char *s){
        int ret = 0, now = 0;
        int len = strlen(s);
        for(int i = 0; i < len; i++){
            int c = s[i];
            if(node[now].next[c]){
                now = node[now].next[c];
            }
            else{
                int p = node[now].fail;
                while(p != -1 && node[p].next[c] == 0){
                    p = node[p].fail;
                }
                if(p == -1) now = 0;
                else now = node[p].next[c];
            }
            get(now);
        }
    }
}ac;


int main(){
    int n;
    while(~scanf("%d", &n)){
        ac.init();
        for(int i = 1; i <= n; i++){
            scanf("%s", b[i]);
            ac.insert(b[i], i);
            ans[i] = 0;
        }
        ac.build();
        getchar();
        scanf("%s", s);
        ac.match(s);
        for(int i = 1; i <= n; i++){
            if(ans[i]){
                printf("%s: %d\n", b[i], ans[i]);
            }
        }
    }
    return 0;
}