HDU5880 Family View(AC自动机)

题意:将匹配的串用‘*’代替

tips:

1 注意内存的使用,据说g++中指针占8字节,c++4字节,所以用g++交会MLE

2 注意这种例子,

1
2
abcd
bc
abc

故失败指针要一直往下走,否则会丢弃一些串

3 当出现非英文字符时应先将指针指向根节点,否则出现

1
1
cy
c,,,,,,,y

时结果为c,,,,,,**(由不止一种Bug造成的),正确的应为c,,,,,,,y,然而很多题解这样也过了~

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
using namespace std;
typedef long long LL;
int Hash[128];

const int N = 1000008, CH = 26;
struct Trie{
    Trie *next[CH];
    Trie *fail;
    int len;
};

int flag[N];

char str[N];

class ACauto{

    Trie tree[N];
    private:
        int nxt;
        Trie *root;

    public:
    void init(){
        root = &tree[0];
        nxt=0;
        memset(&tree[0], 0, sizeof(Trie));
        memset(flag, 0, sizeof(flag));
    }

    void insert(char *s){
        Trie *p = root;
        int i;
        for(i = 0; s[i]; i++){
            int c = Hash[s[i]];
            if(!p -> next[c]){
                memset(&tree[++nxt], 0, sizeof(Trie));
                p -> next[c] = &tree[nxt];
            }
            p = p -> next[c];
        }
        //p -> cnt = 1;
        //p -> cnt++;//用于统计
        p -> len = i;

    }

    void build(){
        queue<Trie *> q;
        q.push(root);
        root -> fail = NULL;
        while(!q.empty()){
            Trie *now = q.front();
            q.pop();
            for(int i = 0; i < CH; i++){
                Trie *son = now -> next[i];
                Trie *tp = (now == root)? root: now -> fail->next[i];
                if(son == NULL){
                    now -> next[i] = tp;//Trie图
                }else{
                    son -> fail = tp;
                    //状态合并(如一个串是另一个串的子串则值域可以合并)
                    //son -> cnt += son -> fail -> cnt;
                    q.push(son);
                }
            }
        }
    }

    //查询匹配次数
    void query(char *s){
        Trie *now = root;
        for(int i = 0; s[i]; i++){
            int c = Hash[s[i]];
            if(c == -1){
                //注意,要将now赋值为root
                now = root;
                continue;
            }
            now = now -> next[c];
            Trie *p = now;
            while(p != root){
                if(p -> len){
                    flag[i - p -> len + 1]--;
                    flag[i + 1]++;
                }
                p = p -> fail;
            }

        }
    }
}ac;

int main(){
    fill(Hash, Hash + 128, -1);
    for(int i = ‘a‘; i <= ‘z‘; i++){
        Hash[i] = i - ‘a‘;
    }

    for(int i = ‘A‘; i <= ‘Z‘; i++){
        Hash[i] = i - ‘A‘;
    }

    int t;
    cin >>t;
    while(t--){
        ac.init();
        int n;
        scanf("%d", &n);
        for(int i  = 0; i < n; i++){
            scanf("%s", str);
            ac.insert(str);
        }
        ac.build();
        getchar();
        gets(str);
        ac.query(str);
        LL cnt = 0;
        for(int i = 0; str[i]; i++){
            cnt += flag[i];
            if(cnt >= 0){
                putchar(str[i]);
            }else{
                putchar(‘*‘);
            }

        }
        printf("\n");
    }

    return 0;
}

  

时间: 2024-10-29 19:10:11

HDU5880 Family View(AC自动机)的相关文章

HDU 5880 Family View (AC自动机)

Family View Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description Steam is a digital distribution platform developed by Valve Corporation offering digital rights management (DRM), multiplayer gaming and socia

2016 年青岛网络赛---Family View(AC自动机)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5880 Problem Description Steam is a digital distribution platform developed by Valve Corporation offering digital rights management (DRM), multiplayer gaming and social networking services. A family view

hdu5880 (AC自动机)

题目链接:hdu5880 Family View 题意:敏感词屏蔽,给一堆敏感词,给一段文本,要求把文本中所有的敏感词用*代替. 题解:对敏感词建出AC自动机,在AC自动机上跑文本,就可以得到文本的每个前缀的最长匹配后缀,扫一遍即可得到结果. 弱弱的说我还不会用AC自动机啊,赛后补题先留下大神的模板吧... 再留个博客改天练练:http://www.cnblogs.com/kuangbin/p/3164106.html 1 #include<cstdio> 2 #include<algo

HDU 5880 Family View (2016 青岛网络赛 C题,AC自动机)

题目链接  2016 青岛网络赛  Problem C 题意  给出一些敏感词,和一篇文章.现在要屏蔽这篇文章中所有出现过的敏感词,屏蔽掉的用$'*'$表示. 建立$AC$自动机,查询的时候沿着$fail$指针往下走,当匹配成功的时候更新$f[i]$ $f[i]$表示要屏蔽以第$i$个字母结尾的长度为$f[i]$的字符串. 原文地址:https://www.cnblogs.com/cxhscst2/p/8452147.html

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

转自kuangbin的AC自动机(赛前最后一博)

有了KMP和Trie的基础,就可以学习神奇的AC自动机了.AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配.           AC自动机 其实 就是创建了一个状态的转移图,思想很重要.           推荐的学习链接: http://acm.uestc.edu.cn/bbs/read.php?tid=4294 http://blog.csdn.net/niushuai666/article/details/7002823 http://hi.baidu.com/nial

AC自动机- 自我总结

AC自动机算法总结  No.1 What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一. 简单的说,KMP用来匹配一个模式串:但如果现在有多个模式串需要在同一篇文章中出现,现在就需要Aho-Corasick automaton算法了. 不要天真的以为AC自动机为auto-Accept,虽然他能让你AC一些题. No.2 My Understanding About Aho-Corasick automato

hdu 5880 AC自动机

Family View Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 20 Problem Description Steam is a digital distribution platform developed by Valve Corporation offering

poj2778 ac自动机+矩阵快速幂

给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://wenku.baidu.com/view/d7b9787f1711cc7931b716b0.html 对于a(i,j)^k  是指从i到j经过k个点的所有情况数 注意对于End数组,如果某个节点如果fail指针End数组为1,那么End[该节点]也是1 string要开全局变量,不然不能运行= = #i