HDU 2896 病毒侵襲 AC自動機題解

來源:互聯網
上載者:User

標籤:blog   使用   os   io   資料   for   2014   ar   

本題是在text裡面尋找key word的增強版,因為這裡有多個text。

那麼就不可以簡單把Trie的葉子標誌記錄修改成-1進行加速了,可以使用其他技術,我直接使用個vis數組記錄已經訪問過的節點,達到加速效果,速度還算挺快的。

不過看discuss裡面有人直接使用Trie,做出了140ms的速度,而且他的程式嚴格來說並不正確,可見本題的資料很水啊。Trie的時間效率肯定比AC自動機低,但是在資料很水的特殊情況下,Trie的速度也可以很快的。

注意兩個細節:

1 病毒也需要安裝順序輸出,不小心就遺漏了。這裡害我錯了幾次。

2 還有就是題目的字元不確定是多少,使用33-94範圍的字元測試答案正確的。


#include <stdio.h>#include <string.h>#include <queue>#include <set>#include <algorithm>using namespace std;const int MAX_N = 501;const int MAX_WORD = 201;const int MAX_M = 1001;const int MAX_TXT = 10001;const int MAX_V = 3;const int ARR_SIZE = 94;char virus[MAX_WORD], web[MAX_TXT];int webNum[MAX_V];int M, N;inline int getIndex(char ch) { return ch - 33; }struct Node{    int n, num, id;    Node *fail;    Node *arr[ARR_SIZE];};void clearNode(Node *rt){    rt->n = 0;    rt->num = 0;    rt->id = 0;    rt->fail = NULL;    for (int i = 0; i < ARR_SIZE; i++)    {        rt->arr[i] = NULL;    }}Node gPool[MAX_N*MAX_WORD], *Trie;int gPoolID;bool vis[MAX_N*MAX_WORD];    //怎麼老是忘記使用visited技術的?void insertTrie(char *virus, int num){    Node *pCrawl = Trie;    for (; *virus; virus++)    {        int id = getIndex(*virus);        if (!pCrawl->arr[id])        {            pCrawl->arr[id] = &gPool[gPoolID++];            clearNode(pCrawl->arr[id]);            pCrawl->arr[id]->id = gPoolID-1;        }        pCrawl = pCrawl->arr[id];    }    pCrawl->n++;    pCrawl->num = num;}void buildFail(){    queue<Node *> qu;    qu.push(Trie);    while (!qu.empty())    {        Node *p = qu.front(); qu.pop();        for (int i = 0; i < ARR_SIZE; i++)        {            if (!p->arr[i]) continue;            p->arr[i]->fail = Trie;            Node *fail = p->fail;            while (fail)            {                if (fail->arr[i])                {                    p->arr[i]->fail = fail->arr[i];                    break;                }                fail = fail->fail;            }            qu.push(p->arr[i]);        }    }}int searchVirus(char *web){    int n = 0;    Node *pCrawl = Trie;    memset(vis, 0, sizeof(bool)*(gPoolID+1));    for (; *web; web++)    {        int i = getIndex(*web);        while (!pCrawl->arr[i] && pCrawl != Trie) pCrawl = pCrawl->fail;        if (pCrawl->arr[i])        {            pCrawl = pCrawl->arr[i];            Node *p = pCrawl;            while (p && !vis[p->id])//使用vis比直接檢查數組值快捷方便            {                if (p->n) webNum[n++] = p->num;                vis[p->id] = true;                p = p->fail;            }            if (n == MAX_V) break;    //At most MAX_V virus one web        }            }    return n;}int main(){    Trie = &gPool[0];    while (scanf("%d", &N) != EOF)    {        gPoolID = 1;        clearNode(Trie);        getchar();        for (int i = 1; i <= N; i++)        {            gets(virus);            insertTrie(virus, i);        }        buildFail();        scanf("%d", &M);        getchar();        int cnt = 0;        for (int i = 1; i <= M; i++)        {            gets(web);            int n = searchVirus(web);            if (n)            {                cnt++;                printf("web %d:", i);                sort(webNum, webNum + n);//Watch out: order!                for (int j = 0; j < n; j++)                {                    printf(" %d", webNum[j]);                }                putchar('\n');            }        }        printf("total: %d\n", cnt);    }    return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.