病毒侵袭持续中


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



Problem Description


小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?


 



Input


第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。


 



Output


按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。


 



Sample Input


3 AA BB CC ooxxCC%dAAAoen....END


 



Sample Output


Hint


 



Source


2009 Multi-University Training Contest 16 - Host by NIT


题目分析:直接开个数组记录每个串出现的次数,ac自动机裸题

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define kind 27

using namespace std;

char str[2000007];
char s[1007][52];

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

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

int head,tail;

void build ( Node *root )
{
    head = tail = 0;
    q[head++] = root;
    root->fail = NULL;
    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 cnt[1007];

void query ( Node *root )
{
    int i = 0;
    Node *p = root;
    while ( str[i] )
    {
        int index = str[i] -'A';
        if ( index < 0 || index >= 26  ) index = 26; 
        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 )
        {
            cnt[temp->id] += temp->count;
            temp = temp->fail;
        }
        i++;
    }
} 

int n;

int main ( )
{
    while ( ~scanf ( "%d" , &n ) )
    {
        memset ( cnt , 0 , sizeof ( cnt ) );
        Node * root = new Node ( );
        for ( int i = 1 ; i <= n ; i++ )
        {
            scanf ( "%s" , s[i] );
            insert ( root , i , s[i] );
        }
        scanf ( "%s" , str );
        build ( root );
        query ( root );
        for ( int i = 1 ; i <= n ; i++ )
            if ( cnt[i] )
                printf ( "%s: %d\n" , s[i] , cnt[i] );
    }
}




 


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define kind 27

using namespace std;

char str[2000007];
char s[1007][52];

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

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

int head,tail;

void build ( Node *root )
{
    head = tail = 0;
    q[head++] = root;
    root->fail = NULL;
    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 cnt[1007];

void query ( Node *root )
{
    int i = 0;
    Node *p = root;
    while ( str[i] )
    {
        int index = str[i] -'A';
        if ( index < 0 || index >= 26  ) index = 26; 
        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 )
        {
            cnt[temp->id] += temp->count;
            temp = temp->fail;
        }
        i++;
    }
} 

int n;

int main ( )
{
    while ( ~scanf ( "%d" , &n ) )
    {
        memset ( cnt , 0 , sizeof ( cnt ) );
        Node * root = new Node ( );
        for ( int i = 1 ; i <= n ; i++ )
        {
            scanf ( "%s" , s[i] );
            insert ( root , i , s[i] );
        }
        scanf ( "%s" , str );
        build ( root );
        query ( root );
        for ( int i = 1 ; i <= n ; i++ )
            if ( cnt[i] )
                printf ( "%s: %d\n" , s[i] , cnt[i] );
    }
}