AC自動機

hdu 3065 病毒侵襲持續中
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

#define WORDLEN 1010
#define PERWORDLEN 55
#define KIND 26
#define MODWORDLEN 2000010

typedef struct AC
{
    AC *fail;
    AC *next[KIND];
    bool leaf;
    int id;
    AC()
    {
        fail = NULL;
        for (int i = 0; i < KIND; ++i){
            next[i] = NULL;
        }
        leaf = false;
        id = -1;
    }
}AC;

char data[WORDLEN][PERWORDLEN];
char segment[MODWORDLEN];
int ret[WORDLEN];

void insertAC(int id, char *str, AC *root)
{
    int i = 0, index;
    AC *p = root;
    while (str[i]){
        index = str[i] - 'A';
        if (p->next[index] == NULL)p->next[index] = new AC();
        p = p->next[index];
        ++i;
    }
    p->leaf = true;
    p->id = id;
}

void buildAC(AC *root)
{
    int i;
    AC *top, *p;
    queue <AC *>Qu;
    root->fail = NULL;
    Qu.push(root);
    while (!Qu.empty()){
        top = Qu.front();
        Qu.pop();
        for (i = 0; i < KIND; ++i){
            if (top->next[i] != NULL){
                if (top == root)top->next[i]->fail = root;
                else {
                    p = top->fail;
                    while (p != NULL){
                        if (p->next[i] != NULL){
                            top->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if (p == NULL)top->next[i]->fail = root;
                }
                Qu.push(top->next[i]);
            }
        }
    }
}

void queryAC(AC *root)
{
    int i = 0, index;
    AC *p = root;
    while (segment[i]){
        index = segment[i] - 'A';
        if (index > 25 || index < 0){
            p = root;
            ++i;
            continue;
        }
        while (p->next[index] == NULL && p != root)p = p->fail;
        p = p->next[index];
        p = (p == NULL ? root : p);
        AC *ac = p;
        while (ac != root){
            if (ac->leaf){
                ret[ac->id] ++;
            }
            ac = ac->fail;
        }
        ++i;
    }
}

int main()
{
    int n;
    while (~scanf ("%d", &n)){
        AC *root = new AC();
        for (int i = 0; i < n; ++i){
            scanf ("%s", data[i]);
            insertAC(i, data[i], root);
        }
        buildAC(root);
        memset(ret, 0, sizeof(ret));
        scanf ("%s", segment);
        queryAC(root);
        for (int i = 0; i < n; ++i){
            if (ret[i]){
                printf ("%s: %d\n", data[i], ret[i]);
            }
        }
    }
    return 0;
}

hdu 2896病毒侵襲

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

#define KIND 128
#define WORDLEN 510
#define PERWORDLEN 210
#define MODWORDLEN 10010
#define MLEN 1010

typedef struct AC
{
    AC *fail;
    AC *next[KIND];
    bool leaf;
    int id;
    AC()
    {
        fail = NULL;
        for (int i = 0; i < KIND; ++i){
            next[i] = NULL;
        }
        leaf = false;
        id = -1;
    }
}AC;

char segment[MODWORDLEN];
vector <int > cnt;

void insertAC(int id, char *str, AC *root)
{
    int i = 0, index;
    AC *p = root;
    while (str[i]){
        index = str[i] - ' ';
        if (p->next[index] == NULL)p->next[index] = new AC();
        p = p->next[index];
        ++i;
    }
    p->leaf = true;
    p->id = id;
    //printf ("id=%d\n", p->id);
}

void buildAC(AC *root)
{
    int i;
    queue <AC* > Qu;
    AC *top, *p;
    root->fail = NULL;
    Qu.push(root);
    while (!Qu.empty()){
        top = Qu.front();
        Qu.pop();
        for (i = 0; i < KIND; ++i){
            if (top->next[i] != NULL){
                if (top == root)top->next[i]->fail = root;
                else {
                    p = top->fail;
                    while (p != NULL){
                        if (p->next[i] != NULL){
                            top->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if (p == NULL)top->next[i]->fail = root;
                }
                Qu.push(top->next[i]);
            }
        }
    }
}

void queryAC(AC *root)
{
    int i = 0, index;
    AC *p = root;
    while (segment[i]){
        index = segment[i] - ' ';
        while (p->next[index] == NULL && p != root)p = p->fail;
        p = p->next[index];
        p = (p == NULL ? root : p);
        AC *ac = p;
        while (ac != root){
            if (ac->leaf){
                cnt.push_back(ac->id);
                //printf ("id = %d\n", ac->id);
            }
            ac = ac->fail;
        }
        ++i;
    }
}

int main()
{
    char keyword[PERWORDLEN];
    int n, m;
    while (~scanf ("%d", &n)){
        AC *root = new AC();
        for (int i = 1; i <= n; ++i){
            scanf ("%s", keyword);
            insertAC(i, keyword, root);
        }
        buildAC(root);
        scanf ("%d", &m);
        int ret = 0;
        for (int i = 1; i <= m; ++i){
            scanf ("%s", segment);
            queryAC(root);
            if (cnt.size() != 0){
                sort(cnt.begin(), cnt.end());
                ret ++;
                printf ("web %d:", i);
                for (int j = 0; j < cnt.size(); ++j){
                    printf (" %d", cnt[j]);
                }
                printf ("\n");
                cnt.clear();
            }
        }
        printf ("total: %d\n", ret);
    }
    return 0;
}

hdu 2222 keywords search

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define KIND 26
#define STACKLEN 500001
#define MAXN 1000010
#define WORDLEN 55

typedef struct ACAutomation
{
    ACAutomation *fail;
    ACAutomation *next[KIND];
    int cnt;
    ACAutomation()
    {
        fail = NULL;
        cnt = 0;
        memset (next, NULL, sizeof(next));
    }
}ACAutomation;

ACAutomation *Qu[STACKLEN];
char segment[MAXN];
char key[WORDLEN];

int head, tail;

void insertACAutomation(char *str, ACAutomation *root)
{
    ACAutomation *p = root;
    int i = 0, index;
    while (str[i]){
        index = str[i] - 'a';
        if (p->next[index] == NULL)p->next[index] = new ACAutomation();
        p = p->next[index];
        ++i;
    }
    p->cnt++;
}

void buildACAutomation(ACAutomation *root)
{
    int i;
    root->fail = NULL;
    Qu[head++] = root;
    while (head != tail){
        ACAutomation *ac = Qu[tail++];
        ACAutomation *p = NULL;
        for (i = 0; i < KIND; ++i){
            if (ac->next[i] != NULL){
                if (ac == root)ac->next[i]->fail = root;
                else {
                    p = ac->fail;
                    while (p != NULL){
                        if (p->next[i] != NULL){
                            ac->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if (p == NULL)ac->next[i]->fail = root;
                }
                Qu[head++] = ac->next[i];
            }
        }
    }
}

int queryACAutomation(ACAutomation *root)
{
    int i = 0, cnt = 0, index;
    ACAutomation *p = root;
    while (segment[i]){
        index = segment[i] - 'a';
        while (p->next[index] == NULL && p != root)p = p->fail;
        p = p->next[index];
        p = (p == NULL ? root : p);
        ACAutomation *ac = p;
        while (ac != root && ac->cnt != -1){
            cnt += ac->cnt;
            ac->cnt = -1;
            ac = ac->fail;
        }
        ++i;
    }
    return cnt;
}

int main()
{
    int t, n;
    scanf ("%d", &t);
    while (t--){
        scanf ("%d", &n);
        head = tail = 0;
        ACAutomation *root = new ACAutomation();
        for (int i = 0; i < n; ++i){
            scanf ("%s", key);
            insertACAutomation(key, root);
        }
        scanf ("%s", segment);
        buildACAutomation(root);
        int ret = queryACAutomation(root);
        printf ("%d\n", ret);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章