题目传送门

  快速的通道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. python进阶(六) 虚拟环境git clone报错解决办法

    在虚拟环境目录,进行git clone xxxxx.git  项目,报如下图错误 解决办法:env GIT_SSL_NO_VERIFY=true git clone xxxx.git

  2. H5进行录音,播放,上传

    废话不说,直接上代码吧 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type&q ...

  3. XXE攻击学习

    环境:lAMP simplexml_load_string.php代码内容 <?php $data = file_get_contents('php://input'); $xml = simp ...

  4. Hibernate基础增删改查语法

    1.创建好Hibernate项目,创建好实体类和测试类,如果不会创建Hibernate项目的同学,点此处:http://www.cnblogs.com/zhaojinyan/p/9336174.htm ...

  5. node.js中net模块创建服务器和客户端(TCP)

    node.js中net模块创建服务器和客户端 1.node.js中net模块创建服务器(net.createServer) // 将net模块 引入进来 var net = require(" ...

  6. 谷歌Cookies无法写入

    写Cookies页面加这个ok: Response.AddHeader("P3P", "CP=CAO PSA OUR");

  7. Eureka (数学组合 + 斜率)

    由于斜率的储存精度不够,所以使用最简分数表示记录. 合并同一个位置上的点,然后统计个数,利用公式先求出至少包含2个点的数量. 然后再是求某位之上的点与某一斜率的个数,那就是每边至少一个点的个数相乘. ...

  8. python urlopen

    Python urllib 库提供了一个从指定的 URL 地址获取网页数据,然后对其进行分析处理,获取想要的数据. urlopen返回 一个类文件对象(fd),它提供了如下方法:read() , re ...

  9. python 文件路径名,文件名,后缀名的操作

    需要使用路径名来获取文件名,目录名,绝对路径等等. 使用os.path 模块中的函数来操作路径名.下面是一个交互式例子来演示一些关键的特性: >>> import os >&g ...

  10. Vector集合——单列集合的“祖宗”类

    是实现可增长的对象数组:所以底层也是数组: 与collection集合不同的是,vector是同步的,意味着是单线程的,意味着效率低,速度慢, 所以在jdk1.2版本之后被ArrayList集合所取代 ...