zoj 3430 Detect the Virus(AC自己主动机)
Detect the Virus
Time Limit: 2 Seconds Memory Limit: 65536 KB
One day, Nobita found that his computer is extremely slow. After several hours' work, he finally found that it was a virus that made his poor computer slow and the virus was activated
by a misoperation of opening an attachment of an email.
Nobita did use an outstanding anti-virus software, however, for some strange reason, this software did not check email attachments. Now Nobita decide to detect viruses in emails by himself.
To detect an virus, a virus sample (several binary bytes) is needed. If these binary bytes can be found in the email attachment (binary data), then the attachment contains the virus.
Note that attachments (binary data) in emails are usually encoded in base64. To encode a binary stream in base64, first write the binary stream into bits. Then take 6 bits from the stream
in turn, encode these 6 bits into a base64 character according the following table:
That is, translate every 3 bytes into 4 base64 characters. If the original binary stream contains 3k + 1 bytes, where k is an integer, fill last bits using zero
when encoding and append '==' as padding. If the original binary stream contains 3k + 2 bytes, fill last bits using zero when encoding and append '=' as padding. No padding is needed when the original binary stream contains 3k bytes.
| Value | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
| Encoding | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | a | b | c | d | e | f |
| Value | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
| Encoding | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | + | / |
For example, to encode 'hello' into base64, first write 'hello' as binary bits, that is: 01101000
01100101 01101100 01101100 01101111
Then, take 6 bits in turn and fill last bits as zero as padding (zero padding bits are marked in bold): 011010 000110 010101 101100 011011 000110 111100
They are 26 6 21 44 27 6 60 in decimal. Look up the table above and use corresponding characters: aGVsbG8
Since original binary data contains 1 * 3 + 2 bytes, padding is needed, append '=' and 'hello' is finally encoded in base64: aGVsbG8=
Section 5.2 of RFC 1521 describes how to encode a binary stream in base64 much more detailedly:
Here is a piece of ANSI C code that can encode binary data in base64. It contains a function, encode (infile, outfile), to encode binary file infile in base64 and output
result to outfile.
Click here to see the reference
C code if you have interest
Input
Input contains multiple cases (about 15, of which most are small ones). The first line of each case contains an integer N (0 <= N <= 512). In the next N distinct
lines, each line contains a sample of a kind of virus, which is not empty, has not more than 64 bytes in binary and is encoded in base64. Then, the next line contains an integer M (1 <= M <= 128). In the following M lines,
each line contains the content of a file to be detected, which is not empty, has no more than 2048 bytes in binary and is encoded in base64.
There is a blank line after each case.
Output
For each case, output M lines. The ith line contains the number of kinds of virus detected in the ith file.
Output a blank line after each case.
Sample Input
3
YmFzZTY0
dmlydXM=
dDog
1
dGVzdDogdmlydXMu 1
QA==
2
QA==
ICAgICAgICA=
Sample Output
2 1
0
Hint
In the first sample case, there are three virus samples: base64, virus and t: ,
the data to be checked is test: virus., which contains the second and the third, two virus samples.
由于解码后的字符的ASCII值是从0~255的。所以最好不要用字符串存储解码后的内容。用int来保存较好一些。
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std; const int kind = 256; //the maximum number of letter
const int N = 50010;
struct Node
{
int next[kind];
int fail;
int cnt;
void build_node() {
for(int i = 0; i < kind; i++)
next[i] = 0;
fail = 0;
cnt = 0;
}
} node[N];
int digit[N], code[N], Size, vis[N];
char file[N], vir[N]; int fun(char ch) //convert char to int
{
if(ch >= 'A' && ch <= 'Z') return ch - 'A';
if(ch >= 'a' && ch <= 'z') return ch - 'a' + 26;
if(ch >= '0' && ch <= '9') return ch - '0' + 52;
if(ch == '+') return 62;
return 63;
} void change(char *str)
{
int i, j, len, t;
vector<int> v;
memset(digit, 0, sizeof(digit));
for(len = strlen(str); str[len-1] == '='; len--) ;
str[len] = '\0';
for(i = 0; i < len; i++)
v.push_back(fun(str[i]));
for(i = 0; i < v.size(); i++) {
for(j = 6 * (i + 1) - 1; j >= 6 * i; j--) {
if(v[i]&1)
digit[j] = 1;
v[i] >>= 1;
}
}
int k = v.size() * 6 / 8; //the number of letter before encode
for(i = 0; i < k; i++) {
for(t = 0, j = 8 * i; j < 8 * (i + 1); j++)
t = (t << 1) + digit[j];
code[i] = t;
}
code[i] = -1;
} void Insert()
{
int cur, index, i;
for(cur = i = 0; code[i] >= 0; i++) {
index = code[i];
if(node[cur].next[index] == 0) {
node[++Size].build_node();
node[cur].next[index] = Size;
}
cur = node[cur].next[index];
}
node[cur].cnt++;
}
void build_ac_automation(int root)
{
queue<int> q;
q.push(root);
while(!q.empty()) {
int cur = q.front(); q.pop();
for(int i = 0; i < kind; i++) {
if(node[cur].next[i]) {
int p = node[cur].next[i];
if(cur)
node[p].fail = node[node[cur].fail].next[i];
q.push(p);
}
else
node[cur].next[i] = node[node[cur].fail].next[i];
}
}
}
int Query()
{
int ans = 0;
for(int i = 0, cur = 0; code[i] >= 0; i++) {
int index = code[i];
cur = node[cur].next[index];
for(int j = cur; j; j = node[j].fail) {
if(!vis[j]) {
ans += node[j].cnt;
vis[j] = 1;
}
}
}
return ans;
} int main()
{
int n, m;
while(~scanf("%d",&n)) {
node[0].build_node();
Size = 0;
for(int i = 1; i <= n; i++) {
scanf("%s",vir);
change(vir);
Insert();
}
build_ac_automation(0);
scanf("%d",&m);
while(m--) {
memset(vis, 0, sizeof(vis));
scanf("%s", file);
change(file);
printf("%d\n", Query());
}
printf("\n");
}
return 0;
}
zoj 3430 Detect the Virus(AC自己主动机)的更多相关文章
- zoj 3430 Detect the Virus(AC自己主动机)
题目连接:zoj 3430 Detect the Virus 题目大意:给定一个编码完的串,将每个字符相应着表的数值转换成6位二进制.然后以8为一个数值,又一次形成字符 串,推断给定询问串是否含有字符 ...
- ZOJ - 3430 Detect the Virus —— AC自动机、解码
题目链接:https://vjudge.net/problem/ZOJ-3430 Detect the Virus Time Limit: 2 Seconds Memory Limit: 6 ...
- ZOJ 3430 Detect the Virus
传送门: Detect the Virus ...
- ZOJ - 3228 Searching the String (AC自己主动机)
Description Little jay really hates to deal with string. But moondy likes it very much, and she's so ...
- ZOJ 3494 BCD Code (AC自己主动机 + 数位DP)
题目链接:BCD Code 解析:n个病毒串.问给定区间上有多少个转换成BCD码后不包括病毒串的数. 很奇妙的题目. . 经典的 AC自己主动机 + 数位DP 的题目. 首先使用AC自己主动机,得到b ...
- ZOJ 3430 Detect the Virus(AC自动机)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3430 题意:给你n个编码后的模式串,和m个编码后的主串,求原来主 ...
- ZOJ 3430 Detect the Virus(AC自动机 + 模拟)题解
题意:问你主串有几种模式串.但是所有串都是加密的,先解码.解码过程为:先把串按照他给的映射表变成6位数二进制数,然后首尾衔接变成二进制长串,再8位8位取变成新的数,不够的补0.因为最多可能到255,所 ...
- ZOJ 3430 Detect the Virus 【AC自动机+解码】
解码的那些事儿,不多说. 注意解码后的结果各种情况都有,用整数数组存储,char数组会超char类型的范围(这个事最蛋疼的啊)建立自动机的时候不能用0来判断结束. #include <cstdi ...
- Zoj 3545 Rescue the Rabbit(ac自己主动机+dp)
标题效果: 鉴于DNA有一个正确的顺序值.请构造一个长度I的DNA在这个序列使DNA正确的顺序值极大.它被认为是负的输出噼啪. .. IDEAS: 施工顺序是,ac己主动机上走,求最大要用到dp dp ...
随机推荐
- async与await线程分配研究
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- day3字典_字符串_文件操作
一.知识回顾 1.jmeter怎样增加压力机:在主控机配置文件 jmeter.perperties 文件中添加对应压力的IP和对应端口,多台压力机IP用","隔开,保证所有负载机和 ...
- 深入理解JVM(7)——类加载器
一.类和类加载器 a) 类加载器的作用:将class文件加载到JVM的方法区,并且在方法区中创建一个java.lang.Class对象作为外界访问这个类的接口. b) 类和 ...
- json文件读写函数
老师代码: import json def op_data(filename,dic=None): if dic:#写入进去 with open(filename,'w',encoding='utf- ...
- 卷积cnn总结
阅读了很多篇文章后,还是觉得有两篇文章很好,所以基本上就吸收搬过来了. 从神经网络到卷积神经网络(CNN) 我们知道神经网络的结构是这样的: 那卷积神经网络跟它是什么关系呢? 其实卷积神经网络依旧是层 ...
- linux shell中break和continue跳出循环
到目前为止,我们已经看到了,创建循环和使用循环来完成不同的任务.有时候,你需要停止循环或跳过循环迭代. 在本教程中,您将了解以下两个语句用于控制 Shell 循环: break 语句 continue ...
- poj1328 Radar Installation(贪心 策略要选好)
https://vjudge.net/problem/POJ-1328 贪心策略选错了恐怕就完了吧.. 一开始单纯地把island排序,然后想从左到右不断更新,其实这是错的...因为空中是个圆弧. 后 ...
- kettle 6.1 按时间循环增量抽取数据
场景:假设有一张表数据量很大,需要按一个时间来循环增量抽取 方法:主要是通过JOB自身调用,实现循环调用,类似于 函数自调用 的循环. 1.JOB全图: 2.获取增量时间,并设置增量时间环境变量 3. ...
- Execution failed for task ':compileDebugAidl'.
昨天终于升级了下Ubuntu系统到16.04LTS,之前是12.04LTS(导致内网一些同事开发的网址无法打开,以及其他工具软件无法安装). 安装完android开发工具,运行之前的project,出 ...
- requirejs amd module load example
person.js /** * This example make use of requireJS to provide a clean and simple way to split JavaSc ...