题目传送门

  快速的通道I

  快速的通道II

题目大意

  给定一堆短串,和一个文本串,问哪些短串在文本串中出现的次数最多。

  我觉得刘汝佳的做法,时间复杂度有问题。只是似乎这道题短串串长太短不好卡。比如给出的串是一坨$a$。暴力跳$last$会比较gg。

  考虑如何计算一个短串在长串中的出现次数。

  当短串在长串的某个位置出现的时候,这意味着它的结束位置在fail树上的祖先中某个状态是短串的终止状态。

  我们会在长串经过的每个状态都去做这样一个操作来统计每个短串出现的次数。

  这个可以看成在fail树上的以根为端点的链上修改操作。

  由于询问可以看成是离线的,所以每次可以单点修改cnt,最后做一次前缀和。

Code

 /**
* UVa Live
* Problem#4670
* Accepted
* Time: 45ms
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
typedef bool boolean; const int MaxNode = , N = , L = ; typedef class TrieNode {
public:
int cnt;
TrieNode* ch[];
TrieNode* fail;
}TrieNode; TrieNode pool[MaxNode];
TrieNode *top; TrieNode* newnode() {
top->cnt = ;
memset(top->ch, , sizeof(top->ch));
top->fail = NULL;
return top++;
} typedef class AhoCorasick {
public:
TrieNode* rt; AhoCorasick() {
top = pool;
rt = newnode();
} TrieNode* insert(char* str) {
TrieNode* p = rt;
for (int i = , c; str[i]; i++) {
c = str[i] - 'a';
if (!p->ch[c])
p->ch[c] = newnode();
p = p->ch[c];
}
return p;
} void build() {
queue<TrieNode*> que;
rt->fail = NULL;
que.push(rt);
while (!que.empty()) {
TrieNode* p = que.front();
que.pop();
for (int i = ; i < ; i++) {
TrieNode *np = p->ch[i];
if (!np) continue;
que.push(np);
TrieNode* f = p->fail;
while (f && !f->ch[i]) f = f->fail;
if (!f)
np->fail = rt;
else
np->fail = f->ch[i];
}
}
} void query(char *str) {
TrieNode *p = rt;
for (int i = ; str[i]; i++) {
int c = str[i] - 'a';
while (p && !p->ch[c]) p = p->fail;
if (!p)
p = rt;
else
p = p->ch[c];
p->cnt++;
}
for (p = top - ; p != pool; p--)
p->fail->cnt += p->cnt;
}
}AhoCorasick; int n;
AhoCorasick ac;
char S[];
char T[N][L];
TrieNode* ps[N]; inline boolean init() {
scanf("%d", &n);
if (!n) return false;
ac = AhoCorasick();
for (int i = ; i <= n; i++) {
scanf("%s", T[i]);
ps[i] = ac.insert(T[i]);
}
scanf("%s", S);
return true;
} inline void solve() {
ac.build();
ac.query(S);
int maxt = ;
for (int i = ; i <= n; i++)
if (ps[i]->cnt > maxt)
maxt = ps[i]->cnt;
printf("%d\n", maxt);
for (int i = ; i <= n; i++)
if (ps[i]->cnt == maxt)
puts(T[i]);
} int main() {
while(init())
solve();
return ;
}

UVa Live 4670 Dominating Patterns - Aho-Corasick自动机的更多相关文章

  1. LA 4670 Dominating Patterns (AC自动机)

    题意:给定n个字符串和一个文本串,查找哪个字符串出现的次数的最多. 析:一匹配多,很明显是AC自动机.只需要对原来的进行修改一下,就可以得到这个题的答案, 计算过程中,要更新次数,并且要映射字符串.如 ...

  2. UVALive 4670 Dominating Patterns (AC自动机)

    AC自动机的裸题.学了kmp和Trie以后不难看懂. 有一些变化,比如0的定义和f的指向,和建立失配边,以及多了后缀连接数组last.没有试过把失配边直接当成普通边(一开始还是先这样写吧). #inc ...

  3. 【暑假】[实用数据结构]UVAlive 4670 Dominating Patterns

    UVAlive 4670 Dominating Patterns 题目:   Dominating Patterns   Time Limit: 3000MS   Memory Limit: Unkn ...

  4. LA 4670 Dominating Patterns (AC自动机)

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

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

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

  6. AC自动机 LA 4670 Dominating Patterns

    题目传送门 题意:训练指南P216 分析:求出现最多次数的字串,那么对每个字串映射id,cnt记录次数求最大就可以了. #include <bits/stdc++.h> using nam ...

  7. UVALive - 4670 Dominating Patterns AC 自动机

    input n 1<=n<=150 word1 word2 ... wordn 1<=len(wirdi)<=70 s 1<=len(s)<=1000000 out ...

  8. UVALive-4670 Dominating Patterns(AC自动机)

    题目大意:找出出现次数最多的模式串. 题目分析:AC自动机裸题. 代码如下: # include<iostream> # include<cstdio> # include&l ...

  9. uvalive 4670 Dominating Patterns

    在文本串中找出现次数最多的子串. 思路:AC自动机模板+修改一下print函数. #include<stdio.h> #include<math.h> #include< ...

随机推荐

  1. cocos2d-x JS 弹出对话框触摸监听(吞噬点击事件遮挡层)

    在游戏中,我们经常会碰到一些弹窗,这些弹窗禁止点透,也就是禁止触摸事件传递到底层,我们称之为遮挡层,这些遮挡层,需要开发遮挡层,我们首先得了解cocos2d-js的触摸传递机制. 根据官方文档,我们可 ...

  2. unity3d连接Sqlite并打包发布Android

    连接Sqlite首先要把dll程序集导入到unity3d工程里面.安装好的unity中可以找到

  3. 30.get和post的区别

    POST和GET的区别 Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个 ...

  4. OBV15 案例5,上M10拉高出货

  5. JavaScript 字符串replace全局替换

    一般使用replace let str = "2018-8-14"; str.replace('-','/')//2018/8-14 并没有替换第二个”-“, 所以我们用正则表达式 ...

  6. python文件基础IO,OS

    #!/usr/bin/python # -*- coding: UTF-8 -*- import os # 导入 Phone 包 #File 对象方法: file对象提供了操作文件的一系列方法. #O ...

  7. 记在Archlinux中安装python的pymssql模块过程中遇到的问题

    为什么要安装这个模块?因为要连接SQLServer数据库. 看到可以使用pyodbc这个模块进行连接,但对odbc不熟悉,所以选用了看起来更简单的 pymssql. 直接执行: pip install ...

  8. QT5 QT4--LNK2019 无法解析的外部符号

    新创建的工程 #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> #include <QtWid ...

  9. 凯撒密码、GDP格式化输出、99乘法表

    1.恺撒密码的编码 s=input('明文:') print('密文:',end='') for i in s: print(chr(ord(i)+3),end='') 附加: print('字符串的 ...

  10. python复习冒泡排序

    冒泡排序: 思路: 先找到最大值放到最右边: #encoding=utf-8 a=[1,9,2,8,3,6,4] print "a before change:",a for i ...