HDU 2896 病毒侵袭(AC自动机)

来源:互联网 发布:网络通信有哪些 编辑:程序博客网 时间:2024/06/07 08:55

病毒侵袭

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 31463 Accepted Submission(s): 7185

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

AC自动机 模板题, 但是Memory Limit Exceeded 整整一下午,MMP,
心疼 感觉不敢再用链表写字典树AC自动机和字典树了 太坑,

再加上 外面32位编译器 拉成比赛GNUc++ 64位编译器 外面内存32000多 里面大概到50000 多更不可能过

所以写两个 一个链表的一个数组 ,建议数组写法

链表:

#include <iostream>#include <string.h>#include <queue>#include <cstdio>#include <algorithm>//#include <bits/stdc++.h>using namespace std;char str[500];char text[10050];//int tag[1003];struct node{    int t;    int num;    node * child[128];    node *fail;    node()    {        t = 0;        num=0;        for (int i=0; i<128; i++)        {            child[i] = NULL;        }        fail =NULL;    }};node *root;void build(int x)   //建立字典树{    //cout<<a<<endl;    node *p;    node * newnode;    int i;    p = root;    for (i=0; i<strlen(str); i++)    {        int m = str[i];        if (p->child[m]==NULL)        {            newnode = new node;            p->child[m] = newnode;        }        p = p->child[m];    }    p->t = x;}void getfail()   //建立fail指针{    int i;    node *p;    node * newnode;    p = root;    //root->fail=NULL;    queue<node *>qu;    qu.push(p);    while (!qu.empty())    {        p = qu.front();        qu.pop();        for (i=0; i<128; i++)        {            if (p->child[i]!=NULL)            {                if (p==root)                {                    p->child[i]->fail = root;                }                else                {                    newnode= p->fail;                    while (newnode!=NULL)                    {                        if (newnode->child[i]!=NULL)                        {                            p->child[i]->fail = newnode->child[i];                            break;                        }                        newnode = newnode->fail;                    }                    if (newnode == NULL)                    {                        p->child[i]->fail = root;                    }                }                qu.push(p->child[i]);            }        }    }}int a[10050],numcount;void query(int id){    node *p=root,*temp;    int len=strlen(text);    for(int i=0; i<len; i++)    {        int pos=text[i];        while(!p->child[pos]&&p!=root) p=p->fail;        p=p->child[pos];        if(!p) p=root;        temp=p;        while(temp!=root)        {            if(numcount>=3) break;            if(temp->t>0&&temp->num!=id)            {                a[numcount++]=temp->t;                temp->num=id;            }            else break;            temp=temp->fail;        }        if(numcount>=3) break;    }}void ended(node *head)   //删除字典树{    for (int i=0; i<128; i++)    {        if (head->child[i]!=NULL)            ended(head->child[i]);    }    delete head;}int main(){    int n,m;    while (~scanf("%d",&n))    {        //ans = 0;        root =new node;        for (int i=1; i<=n; i++)        {            scanf("%s",str);            build(i);        }        int sumbd = 0;         getfail();        scanf("%d",&m);        for (int i=1; i<=m; i++)        {            numcount=0;            //memset(tag,0,sizeof(tag));            bool flag = false;  //初始化无病毒            scanf("%s",text);            query(i);            //cout<<numcount<<endl;            if (numcount>0)            {                sumbd++;                flag = true; //有病毒                printf ("web %d: ",i);                sort(a, a+numcount);                for (int j=0; j<numcount-1; j++)                {                     printf("%d ",a[j]);                }                 printf("%d\n",a[numcount-1]);            }        }         printf("total: %d\n",sumbd);        // ended(root);    }    return 0;}

数组构建的写法

#include <iostream>#include <stdio.h>#include <string.h>#include <queue>#include <algorithm>using namespace std;const int maxn = 500000;//const int allSon = 128;char str[510];  //模式串char text[10010];  //文本串int node[maxn][128];int id,index[maxn],fail[maxn],num[maxn],vis[maxn],cnt,ans[5];void init() {    memset(node[0],-1,sizeof(node[0]));    num[0] = 0;     //num[i]代表以第i个节点为结尾的单词个数    index[0] = 0;   //用来存放模式串的编号    fail[0] = -1;  //fail指针    id = 1;   //节点编号}void buildtree(int x) {   //建立字典树    int p = 0;    int i = 0;    while(str[i] != '\0') {        int ch = str[i];        if(node[p][ch] == -1) {            memset(node[id],-1,sizeof(node[id]));            num[id] = 0;            fail[id] = -1;            node[p][ch] = id++;        }        p = node[p][ch];        i++;    }    num[p]=1;    index[p] = x;}void getfail() {    int p = 0;    queue<int>qu;    qu.push(p);    while(!qu.empty()) {        p = qu.front();        qu.pop();        for(int i = 0; i < 128; i++) {            if(node[p][i] != -1) {                if(p == 0) {                    fail[node[p][i]] = 0;                }                else {                    int temp = fail[p];                    while(temp != -1) {                        if(node[temp][i] != -1) {                            fail[node[p][i]] = node[temp][i];                            break;                        }                        temp = fail[temp];                    }                    if(temp == -1)                        fail[node[p][i]] = 0;                }                qu.push(node[p][i]);            }        }    }}void find_AC() {    int p = 0;    int i = 0;    cnt = 0;    memset(vis,0,sizeof(vis));    while(text[i] != '\0') {        int ch = text[i];        while(node[p][ch]==-1 && p != 0)            p = fail[p];        p = node[p][ch];        if(p == -1) p = 0;        int temp = p;        while(temp!=0 && vis[temp]==0) {            if(num[temp]>0) {                ans[cnt++] = index[temp];                if(cnt == 3)                    break;            }            vis[temp] = 1;            temp = fail[temp];        }        if(cnt == 3)            break;        i++;    }}int main() {    int N,M;    while(~scanf("%d",&N)) {        init();        for(int i = 1; i <= N; i++) {            scanf("%s",str);            buildtree(i);        }        getfail();        scanf("%d",&M);        int total = 0;        for(int i = 1; i <= M; i++) {            scanf("%s",text);            find_AC();            if(cnt) {                total++;                printf("web %d:",i);                sort(ans,ans+cnt);                for(int i = 0; i < cnt; i++) {                    printf(" %d",ans[i]);                }                printf("\n");            }        }        printf("total: %d\n",total);    }    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果手机上的邮件删了怎么办 手机qq邮箱独立密码忘记了怎么办 哺乳期吃了人参回奶了怎么办? 扣扣邮箱里的邮件过期了怎么办 一体机的管理员账号被删除了怎么办 手机里的邮箱重要吗删除了怎么办 华为荣耀10账号邮箱忘记了怎么办 大陆微信号在台湾登录不上怎么办 威纶触摸屏被禁止到反编译了怎么办 微信公众号邮箱被占用怎么办 京东绑定的手机号不用了怎么办 绑定微信的手机号不用了怎么办 绑定支付宝的手机号不用了怎么办 百度账号手机号换了密码忘了怎么办 换手机好了华为账号密码忘了怎么办 苹果手机忘了id账号和密码怎么办 金立手机账号密码忘了怎么办 乐视手机账号密码忘了怎么办 企业邮箱发出去邮件撤不回来怎么办 餐厅加热保温设备零线带电怎么办 小米手机不小心把照片删了怎么办 华为手机不小心把照片删了怎么办 网易邮箱被改成别人的姓名怎么办 苹果手机忘记id密码和邮箱怎么办 163邮箱下载的附件没有了怎么办 小米自带浏览器打开网页太慢怎么办 再歪一点授权码忘记了怎么办 注册支付宝的手机号不用了怎么办 手机号被别人注册了支付宝怎么办 支付宝账号密码都忘了怎么办 申请微信公众号邮箱被占用怎么办 邮箱注册微博需要手机验证怎么办 苹果手机的ad码忘记了怎么办 苹果手机酷狗音乐没有声音怎么办 在手机屏上不能缷载软件怎么办? 手机酷狗音乐下载歌曲要钱怎么办 酷狗下载歌曲后歌词不见了怎么办 手机酷我音乐缓冲文件损坏怎么办 苹果手机音乐里的歌删掉了怎么办 上课学生把粉笔擦藏起来了怎么办 手机没法解压10g压缩包怎么办