zoukankan      html  css  js  c++  java
  • BZOJ 3172 [Tjoi2013]单词 AC自动机Fail树

    题目链接:【http://www.lydsy.com/JudgeOnline/problem.php?id=3172】

    题意:给出一个文章的所有单词,然后找出每个单词在文章中出现的次数,单词用标点符号隔开。

    题解:时间很坑啊,朴素的做法是,先在AC自动机上插入单词,并记录下每个单词,然后用每个单词去维护答案。但是这样做时间空间都不允许,只有在插入的时候维护答案。过程是这样的,在插入的时候,每经过一个点,该节点的值加一,同时记录单词末尾的位置,然后在求玩Fail的时候,倒着走回去就可以了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2024 * 1024 + 15;
    char tmp[maxn];
    struct Aho_C
    {
        int Next[maxn][26], Fail[maxn], pos[maxn], cnt[maxn];
        int que[maxn], st, ed;
        int root, sz;
        int newnode()
        {
            for(int i = 0; i < 26; i++) Next[sz][i] = 0;
            cnt[sz] = 0;
            sz++;
            return sz - 1 ;
        }
        void init()
        {
            sz = 0;
            root = newnode();
        }
        void Insert(char buf[], int id)
        {
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++)
            {
                if(!Next[now][buf[i] - 'a'])
                    Next[now][buf[i] - 'a'] = newnode();
                now = Next[now][buf[i] - 'a'];
                cnt[now]++;
            }
            pos[id] = now;
        }
        void getFail()
        {
            st = ed = 1;
            for(int i = 0; i < 26; i++)
                if(Next[root][i])
                    que[ed++] = Next[root][i];
            while(st != ed)
            {
                int u = que[st++];
                for(int i = 0; i < 26; i++)
                {
                    int &v = Next[u][i];
                    if(!v)
                    {
                        v = Next[Fail[u]][i];
                        continue;
                    }
                    Fail[v] = Next[Fail[u]][i];
                    que[ed++] = v;
                }
            }
            for(int i = ed - 1; i >= 1; i--) cnt[Fail[que[i]]] += cnt[que[i]];
        }
    } ac;
    int main()
    {
        int N;
        scanf("%d", &N);
        ac.init();
        for(int i = 1; i <= N; i++)
        {
            scanf("%s", tmp);
            ac.Insert(tmp, i);
        }
        ac.getFail();
        for(int i = 1; i <= N; i++) printf("%d
    ", ac.cnt[ac.pos[i]]);
        return 0;
    }
    

      

  • 相关阅读:
    jvm2-垃圾回收
    Elasticsearch脑裂问题详细分析以及解决方案
    ThreadLocal原理(基于jdk1.8)
    seata-分布式事务-学习笔记
    Java中的数组
    HAProxy 详细配置说明
    (基础)--- 约数
    (基础)--- Trie树
    Oracle 数据类型对比 不同数据类型对数据空间占用及查询效率影响
    python F score打分
  • 原文地址:https://www.cnblogs.com/pealicx/p/7617840.html
Copyright © 2011-2022 走看看