HDU3065 病毒侵袭持续中 —— AC自动机
题目链接:https://vjudge.net/problem/HDU-3065
病毒侵袭持续中
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15743    Accepted Submission(s): 5343
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
AA
BB
CC
ooxxCC%dAAAoen....END
CC: 1
Hit:
题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。
计数策略也可一定程度上从Sample中推测。
题解:
1.把每个病毒加入Trie树中,并记录其编号。
2.将“万恶之源”与Trie树进行匹配,统计每个病毒出现的次数。
注:在匹配的过程中,如果出现Trie树之外的字符,那么必定不能匹配,所以直接把指针指向root,然后继续下一个字符。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e5+; //id为病毒的编号, sum[]用于记录每个病毒出现的次数
int id, sum[];
struct Trie
{
const static int sz = , base = 'A';
int next[MAXN][sz], fail[MAXN], end[MAXN];
int root, L; int newnode()
{
for(int i = ; i<sz; i++)
next[L][i] = -;
end[L++] = ;
return L-;
} void init()
{
L = ;
root = newnode();
} void insert(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = ; i<len; i++)
{
if(next[now][buf[i]-base] == -)
next[now][buf[i]-base] = newnode();
now = next[now][buf[i]-base];
}
end[now] = id;
} void build()
{
queue<int>Q;
fail[root] = root;
for(int i = ; i<sz; i++)
{
if(next[root][i] == -)
next[root][i] = root;
else
fail[next[root][i]] = root, Q.push(next[root][i]);
}
while(!Q.empty())
{
int now = Q.front();
Q.pop();
for(int i = ; i<sz; i++)
{
if(next[now][i] == -)
next[now][i] = next[fail[now]][i];
else
fail[next[now][i]] = next[fail[now]][i], Q.push(next[now][i]);
}
}
} void query(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = ; i<len; i++)
{
//如果出现Trie树之外的字符,那么必定不能匹配,直接把指针指向root,然后进行下一个字符。
if(buf[i]<'A' || buf[i]>'Z')
{
now = root;
continue;
}
now = next[now][buf[i]-base];
int tmp = now;
while(tmp != root)
{
if(end[tmp]) sum[end[tmp]]++;
tmp = fail[tmp];
}
}
}
}; Trie ac;
char buf[], virus[][];
int main()
{
int n;
while(scanf("%d", &n)!=EOF)
{
ac.init();
for(int i = ; i<=n; i++)
{
id = i;
scanf("%s", virus[i]);
ac.insert(virus[i]);
}
ac.build(); scanf("%s", buf);
memset(sum, , sizeof(sum));
ac.query(buf); for(int i = ; i<=n; i++)
if(sum[i])
printf("%s: %d\n", virus[i], sum[i]);
}
return ;
}
HDU3065 病毒侵袭持续中 —— AC自动机的更多相关文章
- hdu3065 病毒侵袭持续中 AC自动机入门题 N(N <= 1000)个长度不大于50的模式串(保证所有的模式串都不相同), 一个长度不大于2000000的待匹配串,求模式串在待匹配串中的出现次数。
		
/** 题目:hdu3065 病毒侵袭持续中 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065 题意:N(N <= 1000)个长度不大于50的 ...
 - hdu----(3065)病毒侵袭持续中(AC自动机)
		
病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
 - HDU-3065 病毒侵袭持续中 AC自动机又是一板子!
		
病毒侵袭持续中 上一题是求出现多少病毒输出病毒序号,而这题输出每个病毒出现的次数.这题有字典树基础都能做出来,把叶子节点用相应的编号标记起来,匹配的时候遍历到叶子节点用一个数组把次数存起来就行了. 有 ...
 - [hdu3065]病毒侵袭持续中(AC自动机)
		
题意:给出多种病毒的号码和特征码,计算在某串中各病毒匹配的次数. 解题关键:AC自动机模板题,多组输入坑人. #include<bits/stdc++.h> using namespace ...
 - HDU   3065   病毒侵袭持续中    (AC自动机)
		
题目链接 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒 ...
 - hdoj 3065 病毒侵袭持续中(AC自动机)
		
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 思路分析:问题需要模式匹配多个模式串,需要注意的是模式串会包含和重叠,需要对AC自动机的匹配过 ...
 - hdu3065 病毒侵袭持续中【AC自动机】
		
病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
 - hdu3065 病毒侵袭持续中
		
题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3065 题目: 病毒侵袭持续中 Time Limit: 2000/1000 MS (Java ...
 - HDU-3065 病毒侵袭持续中 字符串问题 AC自动机
		
题目链接:https://cn.vjudge.net/problem/HDU-3065 题意 跟上一道题是几乎一模一样,这次是统计关键词的出现次数 一个相当坑的地方,注意多组样例 思路 套模版 改in ...
 
随机推荐
- PV、PVC、StorageClass讲解
			
PV.PVC.StorageClass讲解 为了方便开发人员更加容易的使用存储才出现的概念.通常我们在一个POD中定义使用存储是这样的方式,我们以hostpath类型来说: apiVersion: v ...
 - RabbitMQ 消费端限流、TTL、死信队列
			
目录 消费端限流 1. 为什么要对消费端限流 2.限流的 api 讲解 3.如何对消费端进行限流 TTL 1.消息的 TTL 2.队列的 TTL 死信队列 实现死信队列步骤 总结 消费端限流 1. 为 ...
 - putnik
			
可将旅行商的路线看作是从n - 1号点出发, 跳着到0号点, 再折返走完之前跳过的点. 想到这个, 暴力就可以得50分. 正解是DP. f[i][j](i > j)表示, 从i开始跳, 并返回至 ...
 - Interface Builder中的技巧
			
在我工作中经常会遇到有人吐槽Xcode中的interface builder(以下简称IB)不好用的开发者.在我看来,IB是一个非常棒的可视化开发工具,可以非常快捷的设置UI控件的大部分常用属性.下面 ...
 - uitableview中文排序问题
			
1,uitableview中涉及到排序的问题,查找资料后发现使用UILocalizedIndexedCollation可以很好处理中文和英文系统下中文的排序.而且如果第一个汉字首字母一样那么就会按照第 ...
 - Android 中状态栏、标题栏、View的大小及区分
			
1.获得状态栏的高度(状态栏相对Window的位置): Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisp ...
 - HBase 基本操作
			
如何添加列族 很简单,跟rdbms一样 直接用alter,但是alter之前必须先disable这个表 ---->disable 'test' ...
 - 怎样隐藏Windows7 系统保留分区
			
安装Windows7操作系统时须要预留出100MB左右的系统保留盘分区.在Windows7激活是必须给它分配盘符,否则无法将其成功激活,但是激活后该盘符永久地显示了出来,怎样将其隐藏掉呢? 1.隐藏前 ...
 - odoo生产物流
			
odoo生产从raw materials location 自动消耗物料,产成品进入到finish productslocation. 而odoo自动产生的MO[manufacture Order], ...
 - jvm基础(1)
			
1.整型数和浮点型数的表示 原码:第一位为符号位(0为正数,1为负数). 反码:符号位不动,源码取反. 正数补码:和原码相同. 负数补码:符号位不动,反码加1. 例如5的二进制表示可以是0000010 ...