题目传送门

  快速的通道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. sqli-labs(十五)(堆叠注入)

    第三十八关: 后面好几关都是堆叠注入.简单介绍下: Stacked injections:堆叠注入.从名词的含义就可以看到应该是一堆sql语句(多条)一起执行.而在真实的运用中也是这样的,我们知道在m ...

  2. caffe中的caffemodel参数提取方法

    需要的文件为:deploy.prototxt caffemodel net = caffe.Net(deploy.txt,caffe_model,caffe.TEST)具体代码: import caf ...

  3. ubuntu安装python-mysqldb

    前期准备: sudo apt-get install  libmysqld-dev sudo apt-get install libmysqlclient-dev sudo apt-get insta ...

  4. Rpgmakermv(16) YEP MainmenuManager

    ---------------------------------------------------------------------------------------------------- ...

  5. 【2017-2-21】C#分支语句,分支嵌套,变量的作用域

    分支语句 句式:if else(必须是if开头,可以是else if或者else结束,也可以直接结束) if(bool型比较表达式) { 如果上面的条件成立,则执行这里面的代码 } else if(b ...

  6. python csv文件转换成xml, 构建新xml文件

    csv文件 code from xml.etree.ElementTree import Element,ElementTree,tostring import json,csv def csvtox ...

  7. SQL数据分析概览——Hive、Impala、Spark SQL、Drill、HAWQ 以及Presto+druid

    转自infoQ! 根据 O’Reilly 2016年数据科学薪资调查显示,SQL 是数据科学领域使用最广泛的语言.大部分项目都需要一些SQL 操作,甚至有一些只需要SQL. 本文涵盖了6个开源领导者: ...

  8. C语言学习感受

    C语言,是我学习的第一种计算机语言,是他作为我编写程序的开始,在学习的时候,先学习了最基础的知识,在语言的理论学习语法上,我逐渐的了解了C语言并且对他有了基础的认识与理解,随着学习内容的不断深入,我逐 ...

  9. mybatis源码解析8---执行mapper接口方法到执行mapper.xml的sql的过程

    上一篇文章分析到mapper.xml中的sql标签对应的MappedStatement是如何初始化的,而之前也分析了Mapper接口是如何被加载的,那么问题来了,这两个是分别加载的到Configura ...

  10. PCB 布线,直角线,差分线,蛇形线

    1.直角线 直角走线的一般标准是PCB布线中要尽量避免的情况,也几乎成为衡量布线好坏的标准之一. 直角走线对信号的影响主要体系那在下面三个方面 1.保教可以等效为传输线是哪个的容性负载,减缓上升时间. ...