• bzoj3940


    AC自动机

    复习一下。。。 可惜又写错了

    我们发现就是把单词建成ac自动机,然后把串在ac自动机上跑一遍,每到一个单词结束点就删除,删除是利用栈,每次弹出单词长度个字符就可以了

    发现两个小问题,strlen很慢,不能写在循环里,danger必须在构造fail时全部传递好,否则在匹配时跑fail会达到n^2

    至于这里danger为什么不转移,我也不是很清楚。。。大概是因为使用了trie图优化,并且不是统计单词出现次数,只是希望尽量找到靠前的单词删除

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    int n, top;
    char s[N], t[N], st[N];
    int mark[N], last[N];
    struct AC {
        int root, cnt;
        int danger[N], child[N][27], fail[N];
        void insert()
        {
            int now = root, len = strlen(t);
            for(int i = 0; i < len; ++i)
            {
                int p = t[i] - 'a';
                if(child[now][p] == 0) child[now][p] = ++cnt;
                now = child[now][p];
            } 
            danger[now] = strlen(t);
        } 
        void build_fail()
        {
            queue<int> q;
            for(int i = 0; i < 26; ++i) if(child[root][i]) q.push(child[root][i]);
            while(!q.empty())
            {
                int u = q.front();
                q.pop();
                for(int i = 0; i < 26; ++i) 
                {
                    if(child[u][i] == 0) child[u][i] = child[fail[u]][i];
                    else
                    {
                        fail[child[u][i]] = child[fail[u]][i];
                        q.push(child[u][i]);
                    }
                }
            }
        }
        void put_string()
        {
            int now = root, len = strlen(s);
            for(int i = 0; i < len; ++i)
            {       
                st[++top] = s[i];
                now = child[now][s[i] - 'a'];
                last[top] = now;
                top -= danger[now];     
                now = last[top];
            }
        }
    } ac;
    int main()
    {
        scanf("%s%d", s, &n);
        for(int i = 1; i <= n; ++i)
        {
            scanf("%s", t);
            ac.insert();
        } 
        ac.build_fail();
        ac.put_string();
        int cnt = 0;
        for(int i = 1; i <= top; ++i) printf("%c", st[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    对返回的json数据重写格式,用特性JsonConverter
    dev 的NavBarControl动态菜单
    获取oracel数据库的结构
    Java-背单词程序(俄语)
    实现同或操作 C++
    输入字符串先用cin后用getline函数失效原因
    C++全局变量与局部变量
    4.Redis事务
    3.持久化配置
    2.常用数据类型
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7327843.html
Copyright © 2020-2023  润新知