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

这题太坑了...........wa了无数次才知道是多case

此外还有一点要注意:因为查询串中有不是大写字母的字符,所以特判之后conitnue,但此时应让p指向根结点,这也是没匹配的一种情况


#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;

struct trie {
    trie *next[26];
    int flag;
    char virus[55];
    int num;
    trie *fail;
    trie() {
        fail = NULL;
        flag  = 0;
        num = 0;
        memset(next,0,sizeof(next));
    }
}*q[55555];

trie *rt = new trie();
int  head,tail;
char keyword[1111][55];
char book[2111111];

void insert(char *key) {
    trie *p = rt;
    char tmp[55];
    strcpy(tmp,key);
    while(*key) {
        int t = *key - 'A';
        if(p->next[t] == NULL) p->next[t] = new trie();
        p = p->next[t];
        key ++;
    }
    p->flag = 1;
    strcpy(p->virus,tmp);
}

void bfs() {
    rt->fail = NULL;
    head = tail = 0;
    q[head++] = rt;
    while(head != tail) {
        trie *t = q[tail++];
        trie *tmp = NULL;
        for(int i=0; i<26; i++) {
            if(t->next[i] != NULL) {
                if(t == rt ) t->next[i]->fail = rt;
                else {
                    tmp = t->fail; //沿着父亲的fail指针走
                    while(tmp != NULL) {
                        if(tmp->next[i] != NULL) {
                            t->next[i]->fail = tmp->next[i];
                            break;
                        }
                        tmp = tmp->fail;
                    }
                    if(tmp == NULL) t->next[i]->fail = rt;
                }
                q[head++] = t->next[i];
            }
        }
    }
}


void query(char *key) {
    trie *p = rt;
    while(*key) {
        int t = *key - 'A';
        if(t < 0 || t >= 26) {
            key ++;
            p = rt;  //相当于没找到匹配的,p应该指回rt
            continue;
        }
        while(p != rt && p->next[t] == NULL) p = p->fail;
        p = p->next[t];
        if(p == NULL) p = rt;
        trie *tmp = p;
        while(tmp != rt && tmp->flag != 0) {
            tmp->num++;
            tmp = tmp->fail;
        }
        key++;
    }
}

void search(char *key) {
    trie *p = rt;
    while(*key) {
        int t = *key - 'A';
        if(p->next[t] == NULL) return ;
        p = p->next[t];
        key++;
    }
    if(p->num != 0) {
        printf("%s: %d\n",p->virus,p->num);
    }
}

void free(trie *p) {
    for(int i=0; i<26; i++) {
        if(p->next[i] != NULL) free(p->next[i]);
    }
    delete p;
}
int main() {
    int n;
    while(cin >> n) {
        getchar();
        memset(q,0,sizeof(q));
        rt = new trie();
        for(int i=0; i<n; i++) {
            gets(keyword[i]);
            insert(keyword[i]);
        }
        bfs();
        gets(book);
        query(book);
        for(int i=0; i<n; i++) {
            search(keyword[i]);
        }
        free(rt);
    }
    return 0;
}


你可能感兴趣的:(HDU 3065 病毒侵袭持续中(AC自动机模板))