关闭

AC自动机(2)--hdu2896(病毒侵袭)(基础题)

标签: hdu2896AC自动机AC自动机模板
310人阅读 评论(0) 收藏 举报
分类:
 病毒侵袭

                                             Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u


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


           这道题建字典树的时候每个节点需要存下当前该单词出现的序号(从1开始),没出现过的用0表示。这道题tmd一直超内存,对,你没看错,就是超内存,靠,多稀奇啊,后面我把每个节点的next数组从128减小到了100才过了的,因为ASCII码可见字符是从32~128,上代码:

#include<stdio.h>  
#include<string.h>  
#include<vector>  
using namespace std;  
char str[10007];  
int ans[1007];  
int head,tail;  
struct node  
{  
    node *next[100];
    node *fail;//失效指针  
    int count,id;//是否为该单词的最后一个节点  
    node()//构造函数初始化  
    {  
        count=0;  
        fail=NULL;  
        memset(next,0,sizeof(next));  
    }  
} *q[500001];//队列,方便用于bfs构造失效指针  
void insert(node *root,char str[],int id)  
{  
    node *p=root;  
    int i=0,index;  
    while(str[i])  
    {  
        index=str[i]-32;  
        if(p->next[index]==NULL)p->next[index]=new node();  
        p=p->next[index];  
        i++;  
    }  
    p->count++;//在单词的最后一个节点count+1,代表一个单词  
    p->id=id;  //存下每个单词出现的序号
}  
void build_ac(node *root)  
{  
    root->fail=NULL;  
    q[head++]=root;  
    while(head!=tail)  
    {  
        node *temp=q[tail++];  
        node *p=NULL;  
        for(int i=0; i<96; i++)  
        {  
            if(temp->next[i]!=NULL)  
            {  
                if(temp==root)temp->next[i]->fail=root;  
                else  
                {  
                    p=temp->fail;  
                    while(p!=NULL)  
                    {  
                        if(p->next[i]!=NULL)  
                        {  
                            temp->next[i]->fail=p->next[i];  
                            break;  
                        }  
                        p=p->fail;  
                    }  
                    if(p==NULL)temp->next[i]->fail=root;  
                }  
                q[head++]=temp->next[i];  
            }  
        }  
    }  
}  
int query(node *root)  
{  
    int i=0,index;  
    node *p=root;  
    int cnt=0;  
    while(str[i])  
    {  
        index=str[i]-32;//减的数要比33小  
        while(p->next[index]==NULL&&p!=root)p=p->fail;  
        p=p->next[index];  
        p=(p==NULL)?root:p;  
        node *temp=p;  
        while(temp!=root&&temp->count>0)//如果存在  
        {  
            ans[temp->id]++;  
            cnt++;  
            temp=temp->fail;  
        }  
        i++;  
    }  
    return cnt;//返回匹配的个数  
}  
int main()  
{  
    int n;  
    while(scanf("%d",&n)!=EOF)  
    {  
        head=tail=0;  
        node *root=new node();  
        for(int i=0; i<n; i++)  
        {  
            scanf("%s",str);  
            insert(root,str,i+1);  
        }  
        build_ac(root);  
        int m;  
        scanf("%d",&m);  
        int maxx=0;  
        int cas=1;  
        while(m--)  
        {  
            memset(str,0,sizeof(str));  
            scanf("%s",str);  
            memset(ans,0,sizeof(ans));  
            int count=query(root);  
            if(count)  
            {  
                printf("web %d:",cas);  
                for(int i=1; i<=n; i++)  
                    if(ans[i]>0)printf(" %d",i);  
                printf("\n");  
                maxx++;  
            }  
            cas++;//带病毒的网站数  
        }  
        printf("total: %d\n",maxx);  
    }  
    return 0;  
}  


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:54916次
    • 积分:1686
    • 等级:
    • 排名:千里之外
    • 原创:105篇
    • 转载:38篇
    • 译文:0篇
    • 评论:3条
    最新评论