病毒侵袭

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



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

 


Source

2009 Multi-University Training Contest 10 - Host by NIT

 
题目分析:就是AC自动机的模板,输出恶心一点,用hash搞下就行,数据超水

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

char str[10007];
int n,m,head,tail;
const int kind = 130;
bool used[502];

struct Node
{
    Node * fail;
    Node * next[kind];
    int count;
    int id;
    Node ( )
    {
        memset ( next , NULL , sizeof ( next ) );
        count = 0;
        fail = NULL;
    }
} *q[500007];

void insert ( Node * root , int id )
{
    Node *p = root;
    int i = 0 , index ;
    while ( str[i] )
    {
        index = str[i];
        if ( p->next[index] == NULL ) 
            p->next[index] = new Node ( );
        p = p->next[index];
        i++;
    }
    p->count++;
    p->id = id;
}

void build ( Node * root )
{
    head = tail = 0;
    root->fail = NULL;
    q[head++] = root;
    while ( head != tail )
    {
        Node *temp = q[tail++];
        Node *p = NULL;
        for ( int i = 0 ; i < kind ; 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 id )
{
    int i = 0 , cnt = 0 , index;
    Node *p = root;
    while ( str[i] )
    {
        index = str[i];
        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 != -1 )
        {
            cnt += temp->count;
            if ( temp->count > 0 )
                used[temp->id] = true;
            temp = temp->fail;
        }
        i++;
    }
    return cnt;
}

int main ( )
{
    while ( ~scanf ( "%d" , &n ) )
    {
       // getchar ( );
       /* for ( int i = 0 ; i <= n ; i++ )
            v[i].clear();
        web.clear();*/
        Node *root =  new Node ( );
        for ( int i = 1 ; i <= n ; i++ )
        {
            scanf ( "%s" , str );
           // gets ( str );
            insert ( root , i );
        }
        build ( root );
        scanf ( "%d" , &m );
       // getchar ( );
        int total = 0;
        for ( int i = 1 ; i <= m ; i++ )
        {
            scanf ( "%s" , str );
           // gets ( str );
            memset ( used , 0 , sizeof ( used ) );
            if ( query ( root , i ) > 0 ) 
            {
                total++;
                printf ( "web %d:" , i );
                for ( int i = 1 ; i <= n ; i++ )
                    if ( used[i] )
                        printf ( " %d" , i );
                puts ( "" );
            }
        }
        printf ( "total: %d\n" , total );
    }
}