题目传送门

-------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题

sol:AC自动机,在fail边的基础上再加一个last边,指向真正有效的节点,跳fail边改成跳last边来跳过无效点。

  • AC自动机

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int MAXN = ;
    struct Trie {
    int son[MAXN][], fail[MAXN], last[MAXN];
    int cnt[MAXN], inde[MAXN]; int tot, root, _max;
    vector<int> vec; string str[];
    int add_node() {
    memset(son[tot], -, sizeof(son[tot]));
    cnt[tot] = ; inde[tot] = -;
    return tot ++;
    }
    void init() {
    tot = _max = ;
    root = add_node();
    }
    void insert(char* s, int id) {
    int p = root;
    for (int i = ; s[i]; i++) {
    int index = s[i] - 'a';
    if (son[p][index] == -)
    son[p][index] = add_node();
    p = son[p][index];
    }
    inde[p] = id;
    str[id] = s;
    }
    void build() {
    queue<int> que;
    fail[root] = last[root] = root;
    for (int i = ; i < ; i++) {
    if (son[root][i] == -) son[root][i] = root;
    else {
    fail[son[root][i]] = root;
    last[son[root][i]] = root;
    que.push(son[root][i]);
    }
    }
    while (!que.empty()) {
    int p = que.front(); que.pop();
    for (int i = ; i < ; i++) {
    if (son[p][i] == -) son[p][i] = son[fail[p]][i];
    else {
    fail[son[p][i]] = son[fail[p]][i];
    if (inde[son[fail[p]][i]] != -)
    last[son[p][i]] = son[fail[p]][i];
    else
    last[son[p][i]] = son[last[p]][i];
    que.push(son[p][i]);
    }
    }
    }
    }
    void slove(char* s) {
    int p = root;
    for (int i = ; s[i]; i++) {
    int index = s[i] - 'a';
    p = son[p][index];
    for (int tmp = p; tmp != root; tmp = last[tmp]) {
    if (inde[tmp] == -) continue;
    cnt[tmp] ++;
    if (cnt[tmp] > _max) {
    _max = cnt[tmp];
    vec.clear();
    vec.push_back(inde[tmp]);
    } else if (cnt[tmp] == _max) {
    vec.push_back(inde[tmp]);
    }
    }
    }
    }
    void output() {
    printf("%d\n", _max);
    sort(vec.begin(), vec.end());
    for (int i = ; i < vec.size(); i++)
    cout << str[vec[i]] << endl;
    }
    } ac;
    char s[];
    int main() {
    int n;
    while (scanf("%d", &n) && n) {
    ac.init();
    for (int i = ; i <= n; i++) {
    scanf("%s", s);
    ac.insert(s, i);
    }
    ac.build(); scanf("%s", s);
    ac.slove(s); ac.output();
    }
    return ;
    }

洛谷-P3796-【模板】AC自动机(加强版)的更多相关文章

  1. 洛谷 - P3966 - 单词 - AC自动机

    https://www.luogu.org/problemnew/show/P3966 因为文本串就是字典本身,所以这个和平时的AC自动机不太一样.平时的query要沿着fail树把子树的出现次数依次 ...

  2. 洛谷.3121.审查(AC自动机 链表)

    题目链接 //删掉一个单词需要前移一段位置,用链表维护就好了 复杂度O(sum(len)) #include <cstdio> #include <cstring> #defi ...

  3. 洛谷 - P2444 - 病毒 - AC自动机

    https://www.luogu.org/problemnew/show/P2444 有点恶心,不太明白fail的意义. #include<bits/stdc++.h> using na ...

  4. 洛谷 P3804 [模板] 后缀自动机

    题目:https://www.luogu.org/problemnew/show/P3804 模仿了一篇题解,感觉很好写啊. 代码如下: #include<cstdio> #include ...

  5. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  6. 洛谷P1120 小木棍 [数据加强版](搜索)

    洛谷P1120 小木棍 [数据加强版] 搜索+剪枝 [剪枝操作]:若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环.因为此时继续 ...

  7. 洛谷P3796 - 【模板】AC自动机(加强版)

    原题链接 Description 模板题啦~ Code //[模板]AC自动机(加强版) #include <cstdio> #include <cstring> int co ...

  8. 洛谷P3796 【模板】AC自动机(加强版)(AC自动机)

    洛谷题目传送门 先膜一发yyb巨佬 orz 想学ac自动机的话,推荐一下yyb巨佬的博客,本蒟蒻也是从那里开始学的. 思路分析 裸的AC自动机,这里就不讲了.主要是这题太卡时了,尽管时限放的很大了.. ...

  9. 洛谷 P3796 【模板】AC自动机(加强版)(AC自动机)

    题目链接:https://www.luogu.com.cn/problem/P3796 AC自动机:复杂度$O( (N+M)\times L )$,N为模式串个数,L为平均长度,M为文章长度. ins ...

  10. 洛谷-P5357-【模板】AC自动机(二次加强版)

    题目传送门 -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题 sol:AC自动机,还是要解决跳fail边产生的重复访问,但 ...

随机推荐

  1. python 简单字符串字典加密

    1 def crypt(source,key): from itertools import cycle result='' temp=cycle(key) for ch in source: res ...

  2. tensorflow---darknet53

    #! /usr/bin/env python# coding=utf-8#=============================================================== ...

  3. ubuntu16+caffe fast-rcnnCPU运行步骤

    //////////////////////////////////////////////////////////////////////////////////////////////////// ...

  4. React编写组件的局部样式

    我们都知道,在Vue的单文件组件中,style标签中编写的样式默认为全局样式,如果我们想编写局部样式, 使用一个scoped关键字就可以. 那么在React中怎么实现呢? (注: 这种方法必须使用类选 ...

  5. Java自学-集合框架 聚合操作

    聚合操作 步骤 1 : 聚合操作 JDK8之后,引入了对集合的聚合操作,可以非常容易的遍历,筛选,比较集合中的元素. 像这样: String name =heros .stream() .sorted ...

  6. sqlmap简单流程使用

    -u “(url)” 1.判断可注入的参数 2.判断可以用那种SQL注入技术来注入 3.识别出哪种数据库 4.根据用户选择,读取哪些数据 sqlmap支持五种不同的注入模式: 1.基于布尔的盲注,即可 ...

  7. 2.Git基本配置

    用户名和邮箱地址是本地git客户端的一个变量 . 用户每次提交代码都会记录用户名和邮箱 . 设置git的用户和邮箱git config [--local | --global | --system] ...

  8. java 面向对象概述, 函数解析

    函数:class FunctionDemo { public static void main(String[] args) { /* int x = 4; System.out.println(x* ...

  9. shift+alt 可对notepadplusplus 打开的文档进行列操作

    shift+alt 可对notepadplusplus 打开的文档进行列操作

  10. 生成随机数(Random类)和获取用户输入(Scanner类)

    生成指定范围内的随机数 Math.random() 生成随机数,随机数在0到1之间,类型是 double. public class randCase { public static void mai ...