【AC自动机】HDU - 2896 病毒侵袭(字典树应该开多大的数组???)

 HDU - 2896 病毒侵袭

  • 题意:N个模式串,M个文本串。对于每个文本串,输出其中出现的模式串的序号。最后一行输出包含模式串的文本串的个数。字符来自于可打印ascii码。

不用说肯定是AC自动机的模板的嘛,但是怎么说,我竟然自己把自己卡在了数组大小上。

字典树结点数到底应该开多大?本来我是开了N*len*100(因为ascii码可打印的个数是90+)。然后编译都没过,确实叭,数组太大了。为了看有没有其他错误的嘛,于是开了N*len运行代码。样例过了之后交了一发T了。于是把Fail树构建给删了(因为没有让求每个模式串的出现次数,所以没必要的,不知道写的时候咋想的,反正写上了,可能顺手了……),删了之后又交了一发,竟然过了!!??

于是开始百度字典树应该开多大数组?然后大部分就是说的是N*len=模式串个数*模式串长度。想想确实好像也是。但是不知道为什么就是觉得……有点诡异。这个AC有点让我不知所措……


ps: 昨天上课的英语老师竟然也是个程序员。他问我coding是喜欢还是迫不得已。我说喜欢。他说他是工作迫不得已。233333333333


AC CODE

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxS = 10004;
const int maxN = 100005;
int total;
struct AC_automat{
    int trie[maxN][100], tot;
    int fail[maxN];
    int times[maxN];
    int endd[maxS];

    void Clear(int rt)
    {
        for(int i = 0; i < 100; ++ i )
            trie[rt][i] = 0;
        fail[rt] = 0;
    }

    void init()
    {
        Clear(0);
        tot = 0;
        total = 0;
    }

    void Insert(char *s, int p)
    {
        int rt = 0;
        for(int i = 0; s[i]; ++ i )
        {
            int id = s[i] - 32;
            if(!trie[rt][id]) { trie[rt][id] = ++ tot; Clear(tot); }
            rt = trie[rt][id];
        }
        endd[p] = rt;
    }

    void build()
    {
        queue<int>q;
        for(int i = 0; i < 100; ++ i) if(trie[0][i]) q.push(trie[0][i]);
        while(!q.empty())
        {
            int rt = q.front(); q.pop();
            for(int i = 0; i < 100; ++ i )
            {
                if(trie[rt][i])
                {
                    fail[trie[rt][i]] = trie[fail[rt]][i];
                    q.push(trie[rt][i]);
                } else trie[rt][i] = trie[fail[rt]][i];
            }
        }
    }

    void getTimes(char *t)
    {
        memset(times, 0, sizeof(times));
        int rt = 0;
        for(int i = 0; t[i]; ++ i )
            ++ times[rt = trie[rt][t[i] - 32]];
    }

    void print(int n, int id)
    {
        vector<int>ans;
        for(int i = 1; i <= n; ++ i)
        {
            if(times[endd[i]])
                ans.push_back(i);
        }
        if(!ans.empty())
        {
            ++ total;
            printf("web %d: ", id);
            int siz = ans.size();
            for(int i = 0; i < siz; ++ i)
                printf("%d%c", ans[i], " \n"[i == siz - 1]);
        }
    }

}ac;

int n, m;
char s[maxS];

int main()
{
    scanf("%d", &n); ac.init();
    getchar();
    for(int i = 1; i <= n; ++ i)
    {
        gets(s);
        ac.Insert(s, i);
    }
    ac.build();
    scanf("%d", &m);
    getchar();
    for(int i = 1; i <= m; ++ i )
    {
        gets(s);
        ac.getTimes(s);
        ac.print(n, i);
    }
    printf("total: %d\n", total);
}
发布了242 篇原创文章 · 获赞 68 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104195325
今日推荐