bzoj3940 censoring 题解(AC自动机)

题目描述

Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty of material to read while waiting around in the barn during milking sessions. Unfortunately, the latest issue contains a rather inappropriate article on how to cook the perfect steak, which FJ would rather his cows not see (clearly, the magazine is in need of better editorial oversight).FJ has taken all of the text from the magazine to create the string S of length at most 10^5 characters. He has a list of censored words t_1 ... t_N that he wishes to delete from S. To do so Farmer John finds the earliest occurrence of a censored word in S (having the earliest start index) and removes that instance of the word from S. He then repeats the process again, deleting the earliest occurrence of a censored word from S, repeating until there are no more occurrences of censored words in S. Note that the deletion of one censored word might create a new occurrence of a censored word that didn‘t exist before.Farmer John notes that the censored words have the property that no censored word appears as a substring of another censored word. In particular this means the censored word with earliest index in S is uniquely defined.Please help FJ determine the final contents of S after censoring is complete.

FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S。他有一个包含n个单词的列表,列表里的n个单词记为t_1...t_N。他希望从S中删除这些单词。 FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词 FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的 请帮助FJ完成这些操作并输出最后的S

输入

The first line will contain S. The second line will contain N, the number of censored words. The next N lines contain the strings t_1 ... t_N. Each string will contain lower-case alphabet characters (in the range a..z), and the combined lengths of all these strings will be at most 10^5.

第一行包含一个字符串S

第二行包含一个整数N

接下来的N行,每行包含一个字符串,第i行的字符串是t_i

输出

The string S after all deletions are complete. It is guaranteed that S will not become empty during the deletion process.

一行,输出操作后的S

多单词匹配显然ac自动机

照常建trie插入

用栈记录匹配字符时指针位置,如果匹配到单词就弹栈回到之前的状态

顺便记录修改后的串

之后直接输出答案

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
struct ac_auto
{
    struct node
    {
        node *son[28],*fail;
        int size;
        node()
        {
            memset(this,0,sizeof(node));
        }
    };
    node *root;
    void ini()
    {
        root=new node();
    }
    void ins(char *s)
    {
        int l=strlen(s+1);
        node *now=root;
        for(int i=1;i<=l;i++)
        {
            if(!now->son[s[i]-‘a‘])now->son[s[i]-‘a‘]=new node();
            now=now->son[s[i]-‘a‘];
        }
        now->size=l;
    }
    void build()
    {
        queue<node*> q;
        for(int i=0;i<26;i++)
        {
            if(root->son[i])
            {
                q.push(root->son[i]);
                root->son[i]->fail=root;
            }
            else root->son[i]=root;
        }
        while(!q.empty())
        {
            node *x=q.front();
            q.pop();
            for(int i=0;i<26;i++)
            {
                if(x->son[i])
                {
                    x->son[i]->fail=x->fail->son[i];
                    q.push(x->son[i]);
                }
                else x->son[i]=x->fail->son[i];
            }
        }
    }
    char ans[100005];int tot=0;
    node *st[100005];
    void query(char *s)
    {
        node *now=root;
        st[0]=root;
        int l=strlen(s+1);
        for(int i=1;i<=l;i++)
        {
            int x=s[i]-‘a‘;
            now=now->son[x];
            st[++tot]=now;
            ans[tot]=s[i];
            if(now->size)tot-=now->size,now=st[tot];
        }
    }
}ac;
char S[100005],str[100005];
int n;
int main()
{
    scanf("%s%d",S+1,&n);
    ac.ini();
    for(int i=1;i<=n;i++)
        scanf("%s",str+1),ac.ins(str);
    ac.build();
    ac.query(S);
    for(int i=1;i<=ac.tot;i++)putchar(ac.ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/Rorschach-XR/p/11025392.html

时间: 2024-10-28 21:00:38

bzoj3940 censoring 题解(AC自动机)的相关文章

3940. [USACO15FEB]Censoring【AC自动机+栈】

Description Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty of material to read while waiting around in the barn during milking sessions. Unfortunately, the latest issue contains a rather inap

【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp

题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运数.给定N和S,计算不大于N的幸运数个数. 输入 输入的第一行包含整数N.接下来一行一个整数M,表示S中元素的数量.接下来M行,每行一个数字串,表示S中的一个元素. 输出 输出一行一个整数,表示答案模109+7的值. 样例输入 20 3 2 3 14 样例输出 14 题解 AC自动机+数位dp 同学

【bzoj4327】JSOI2012 玄武密码 AC自动机

题目描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在进香河地区发现了带有玄武密码的文字.更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联.于是,漫长的破译工作开始了. 经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的元素分别是‘E’,‘S’,‘W’,‘N’,代表了东南西北四

【BZOJ3940】【Usaco2015 Feb】Censoring AC自动机

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44960463"); } 题意: 题意同BZOJ3942,不过要删除的串是多串 http://blog.csdn.net/vmurder/article/details/44959895 题解: --思路一模一样,除了不用kmp用AC

【AC自动机】Censoring

[题目链接] https://loj.ac/problem/10059 [题意] 有一个长度不超过  1e5 的字符串 .Farmer John 希望在 T 中删掉 n 个屏蔽词(一个屏蔽词可能出现多次),这些词记为 P1,P2……Pn. [题解] 利用栈来进行匹配删除即可. 1.建模式串的AC自动机.(结尾位置记录长度) 2.利用文本串跑一遍AC自动机. 3.在跑的过程中,如果遇到屏蔽字的结尾时,相应操作为:1.把栈里弹出模式串的长度,2.同时文本串继续跑. 4.跑的过程中还需要一个辅助的数组

HDU 2896 病毒侵袭 AC自动机题解

本题是在text里面查找key word的增强版,因为这里有多个text. 那么就不可以简单把Trie的叶子标志记录修改成-1进行加速了,可以使用其他技术,我直接使用个vis数组记录已经访问过的节点,达到加速效果,速度还算挺快的. 不过看discuss里面有人直接使用Trie,做出了140ms的速度,而且他的程序严格来说并不正确,可见本题的数据很水啊.Trie的时间效率肯定比AC自动机低,但是在数据很水的特殊情况下,Trie的速度也可以很快的. 注意两个细节: 1 病毒也需要安装顺序输出,不小心

HDU 3065 病毒侵袭持续中 AC自动机题解

其实本题比HDU的病毒侵袭1还简单,不过有一个陷阱卡到我了:就是搜索text的时候,当遇到的字母不是大写字母的时候,那么就要重新从根节点开始搜索,否则就会答案错误. 那么一点陷阱,居然没想到啊. 教训啊:看来对不太平常的地方,需要更加深入的思考,才能发现其中的陷阱,否则就WA了. #include <stdio.h> #include <string.h> #include <queue> using std::queue; const int MAX_N = 1001

【HDU2222】【Keywords Search】AC自动机,有详细注释题解。

题意:给定N个单词,和一个字符串S,求这N个单词在字符串S中,有多少个出现过. 题解:AC自动机裸题一枚. AC自动机是基于字典树的一种KMP思想高级算法,用于多字串匹配.就是把字典树建好,然后模仿KMP的前缀数组"pre[]",在字典树内处理了一个fail(失败指针),失配时顺着往前找,并寄托于此以得到答案. 直接附代码,里面有详解.(数组模拟版!!!指针神马的都去回收站吧!) 结构体+注释版本: #include <queue> #include <cstdio&

POJ 1204 Word Puzzles AC自动机题解

AC自动机的灵活运用,本题关键是灵活二字. 因为数据不是很大,时间要求也不高的缘故,所以本题有人使用暴力法也过了,有人使用Trie也过了. 当然有人使用AC自动机没AC的,在讨论区里喊AC自动机超时的,那是因为不会灵活运用,或者是硬套模板的,AC了速度也不会快. 给出本人的算法思路: 1 把需要查找的关键字建立Trie, 然后构造AC自动机 2 查找的时候分八个方向查找,比如棋盘是board[N][M],那么就可以循环i(0->N-1),然后每次把board[i]当做一个文本,做过HDU的key