病毒侵袭
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12989 Accepted Submission(s): 3346
Problem Description
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~
但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
Input
第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
Sample Input
3
aaa
bbb
ccc
2
aaabbbccc
bbaacc
Sample Output
web 1: 1 2 3
total: 1
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12989 Accepted Submission(s): 3346
Problem Description
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~
但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
Input
第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
Sample Input
3
aaa
bbb
ccc
2
aaabbbccc
bbaacc
Sample Output
web 1: 1 2 3
total: 1
入门的题。 之前模版会把在query 访问过的 cnt 改为-1。没有及时发觉,导致wa了好多次。
还有就是next数组要大点,可以直接开128 。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen("input.txt","r",stdin)
#define FF freopen("output.txt","w",stdout)
#define N 10005
#define M 1000005
const int kind = 130;
char ss[10010];//输入的模式串
struct node
{
node *fail;//失败指针
node *next[kind];//Trie每个节点的子节点(最多26个子母)
int cnt;//是否为该单词的最后一个节点
node ()
{//构造函数初始化
fail = NULL;
cnt = 0;
memset(next,NULL,sizeof(next));
};
};
char str[210];//输入的单词
vector <int > arr;
queue<node*> qq;//队列构造失败指针
//建Trie树
void BuildTree (node *root,int index)
{
node *p = root;
int i = 0,id;
while (str[i])
{
id = str[i];
if (p->next[id] == NULL)
p->next[id] = new node();
p = p->next[id];
i++;
}
(p->cnt) = index;
}
/*
bfs求失败指针
设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,
他的儿子中也有字母为C的节点。然后把当前节点的失败指针指向那个字母也为C的儿子。
如果一直走到了root都没找到,那就把失败指针指向root。
*/
void bfs(node *root)
{
while (!qq.empty()) qq.pop();
int i;
root->fail = NULL;
qq.push(root);
root->fail = NULL;
node *tmp,*p;
while (!qq.empty())
{
tmp = qq.front();
qq.pop();
p = NULL;
for (i = 0; i < kind; i++)
{
if (tmp->next[i] != NULL)
{
p = tmp->fail;
while (p && !p->next[i]) //p:当前点 tmp不是根 !p->next[i]:还能找到i这个字母 在
p = p->fail;
if (!p)
tmp->next[i]->fail = root;
else
tmp->next[i]->fail = p->next[i];
qq.push(tmp->next[i]);
}
}
}
}
/*
AC自动机主程序
当前字符不匹配,则去当前节点失败指针所指向的字符继续匹配,匹配过程随着指针指向root 或者 匹配到下一个字母 结束。
*/
int has[600];
int AC_run(node *root)
{
int i = 0,ans = 0,id;
node *p = root;
while (ss[i])
{
id = ss[i] ;
while (!p->next[id] && p != root)//!p->next[id] p点下面没有id字母
p = p->fail;
p = p->next[id];
if(!p) p = root;// while结束 如果上面的p 最后是根的情况下。
node *tmp = p;
while (tmp != root && tmp->cnt != -1)
{//cnt=-1 表示已经计算过
if(tmp->cnt!=0)
{
ans += tmp->cnt;
has[tmp->cnt]=1;
}
//tmp->cnt = -1; //不能改
tmp = tmp->fail;
}
i++;
}
return ans;
}
int main ()
{
int t;
int n;
while (scanf("%d",&n)!=EOF)
{
node *root = new node();
for(int i=1;i<=n;i++)
{
scanf("%s",str);
BuildTree(root,i);
}
bfs(root);
int m;
scanf("%d",&m);
int total=0;
for(int i=1;i<=m;i++)
{
memset(has,0,sizeof has);
scanf("%s",ss);
if(AC_run(root))
{
total++;
printf("web %d:",i);
for(int j=1;j<=n;j++)
{
if(has[j])
printf(" %d",j);
}
puts("");
}
}
printf("total: %d\n",total);
}
return 0;
}
/*
2
adf
dfa
2
adffff
adfaddafdfa
web 1: 1
web 2: 1 2
total: 2
*/