Dominating Patterns (AC 自动鸡模版题, 出现次数最多的子串)

传送门

题意: 给你n个模式串, 再给你一个 文本串,问模式串在文本串中出现次数最多是多少。

   出现次数最多的模式串有哪些。

解: 模版题。

#include <bits/stdc++.h>
#define LL long long
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define mem(i, j) memset(i, j, sizeof(i))
using namespace std;
const int N = 150 * 70 + 5, M = 26;
map<string, int> vis;
char s[1000005], b[155][100];
struct Trie {
    int a[N][M], tot, val[N], Fail[N];
    void init() {
        mem(a[0], -1); tot = 1; val[0] = -1;
    }
    int get(char Q) {
        return Q - ‘a‘;
    }
    void join(char s[], int v) {
        int len = strlen(s); int now = 0;
        rep(i, 0, len - 1) {
            int id = get(s[i]);
            if(a[now][id] == -1) {
                mem(a[tot], -1);
                val[tot] = -1;
                a[now][id] = tot++;
            }
            now = a[now][id];
        }
        val[now] = v;
    }
    void getFail() {
        queue<int>Q;  while(!Q.empty()) Q.pop();
        Fail[0] = 0;
        rep(i, 0, M - 1) {
            if(a[0][i] == -1) a[0][i] = 0;
            else {
                Fail[a[0][i]] = 0;
                Q.push(a[0][i]);
            }
        }
        while(!Q.empty()) {
            int now = Q.front(); Q.pop();
            rep(i, 0, M - 1) {
                if(a[now][i] == -1) a[now][i] = a[Fail[now]][i];
                else {
                    Fail[a[now][i]] = a[Fail[now]][i];
                    Q.push(a[now][i]);
                }
            }
        }
    }
    int num[155];
    void query(char s[], int n) {
        mem(num, 0);
        int len = strlen(s);
        int now = 0;
        rep(i, 0, len - 1) {
            now = a[now][get(s[i])];
            int tmp = now;
            while(tmp != 0) {
                if(val[tmp] != -1) num[val[tmp]]++;
                tmp = Fail[tmp];
            }
        }
        int ma = 0;
        rep(i, 1, n) {
            ma = max(ma, num[i]);
        }
        printf("%d\n", ma);
        rep(i, 1, n) {
            if(num[vis[b[i]]] == ma) {
                printf("%s\n", b[i]);
            }
        }
    }
};
Trie AC;
int main() {
    int n;
    while(scanf("%d", &n) && n) {
        AC.init(); vis.clear();
        rep(i, 1, n) {
            scanf("%s", b[i]);
            AC.join(b[i], i);
            vis[b[i]] = i;
        }
        AC.getFail();
        scanf("%s", s);
        AC.query(s, n);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Willems/p/12001225.html

时间: 2024-10-13 06:06:36

Dominating Patterns (AC 自动鸡模版题, 出现次数最多的子串)的相关文章

UVALive 4670 Dominating Patterns --AC自动机第一题

题意:多个模板串,一个文本串,求出那些模板串在文本串中出现次数最多. 解法:AC自动机入门模板题. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <string> #include <vector> #in

uva 1449 - Dominating Patterns(AC自动机)

题目练级:uva 1449 - Dominating Patterns 题目大意:有一个由小写字母组成的字符串集和一个文本T,要求找出那些字符串在文本中出现的次数最多. 解题思路:将字符串集建立AC自动机,然后传入T进行匹配,对每个匹配上的字符串多应次数加1,最后找出最大值.出现次数与最大值相同的字符串输出.注意字符集中出现相同字符的情况. #include <cstdio> #include <cstring> #include <queue> #include &l

LA4670 Dominating Patterns AC自动机模板

Dominating Patterns 每次看着别人的代码改成自己的模板都很头大...空间少了个0卡了好久 裸题,用比map + string更高效的vector代替蓝书中的处理方法 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7

LA 4670 出现次数最多的子串 (AC自动机模板题)

Dominating Patterns Time Limit:3000MS   Memory Limit:Unknown   64bit IO Format:%lld & %llu [Submit]  [Go Back]  [Status] Description The archaeologists are going to decipher a very mysterious ``language". Now, they know many language patterns; ea

LA 4670 Dominating Patterns (AC自动机)

题意:给定一个一篇文章,然后下面有一些单词,问这些单词在这文章中出现过几次. 析:这是一个AC自动机的裸板,最后在匹配完之后再统计数目就好. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <ios

POJ 1204 Word Puzzles | AC 自动鸡

题目: 给一个字母矩阵和几个模式串,矩阵中的字符串可以有8个方向 输出每个模式串开头在矩阵中出现的坐标和这个串的方向 题解: 我们可以把模式串搞成AC自动机,然后枚举矩阵最外围一层的每个字母,向八个方向进行匹配 代码中danger标记为判断这个节点是不是一个模式串的结尾, 这道题可以直接字符串反向构建AC自动机,匹配到的就是开头(代码是正向) #include<cstdio> #include<algorithm> #include<cstring> #include&

UVA 11468 Substring (记忆化搜索 + AC自动鸡)

传送门 题意: 给你K个模式串, 然后,再给你 n 个字符, 和它们出现的概率 p[ i ], 模式串肯定由给定的字符组成. 且所有字符,要么是数字,要么是大小写字母. 问你生成一个长度为L的串,不包含任何模式串的概率是多少. 解: 记忆化搜索 +  AC自动机. 对模式串建一个AC自动机, 不需要last[ ] 和 val[ ], 只需要一个 metch[ ]. 维护一下这个点是否是某个模式串的最后一个字符节点,若是,则这个点不能走. 然后, 剩下的就是从根节点,随便走 L 步, 记得要记忆化

POJ 2778 DNA Sequence (矩阵快速幂 + AC自动鸡)

题目:传送门 题意: 给你m个病毒串,只由(A.G.T.C) 组成, 问你生成一个长度为 n 的 只由 A.C.T.G 构成的,不包含病毒串的序列的方案数. 解: 对 m 个病毒串,建 AC 自动机, 然后, 这个AC自动机就类似于一张有向图, 可以用邻接矩阵存这张有向图. 最多10个病毒串, 每个病毒串长度不超过 10, 那最多是个 100 * 100 的矩阵, 可以接受. 最后用矩阵快速幂加速推导. #include<cstdio> #include<cstring> #inc

UVALive - 4670 Dominating Patterns AC 自动机

input n 1<=n<=150 word1 word2 ... wordn 1<=len(wirdi)<=70 s 1<=len(s)<=1000000 output 最多出现次数 出现最多的串,按输入顺序输出,可能出现相同串,也要输出 做法:用一个end数组记下每个串结尾的字符的下标,对应val为1,每次找到就将val++,然后找到最大的val,输出最大val对应的字符串 1 #include <cstdio> 2 #include <queue