zoukankan      html  css  js  c++  java
  • HDU 3065 病毒侵袭持续中(AC自动机)

    病毒侵袭持续中

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


    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
    AA: 2 CC: 1
    Hint
    Hit: 题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。 计数策略也可一定程度上从Sample中推测。
     
     
      1 /* 
      2 hdu 3065 题意很简单 
      3 */  
      4 #include <iostream>   
      5 #include<string.h>  
      6 #include<stdlib.h>  
      7 using namespace std;   
      8     
      9 int biaoshi[1010];  
     10 char chuan[1100][55];  
     11 const int kind = 26; //!!!!!!!!!!!!!!!!!!  
     12   
     13 struct node{    
     14     node *fail;       //失败指针  
     15     node *next[kind];   
     16     int count;        //是否为该单词的最后一个节点  
     17     node(){           //构造函数初始化  
     18         fail=NULL;   
     19         count=0;   
     20         memset(next,NULL,sizeof(next));   
     21     }   
     22 }*q[50000];          //队列,方便用于bfs构造失败指针  
     23 char keyword[510];     //输入的单词  
     24 char str[2000010];    //模式串  
     25 int head,tail;        //队列的头尾指针  
     26     
     27 void insert(char *str,node *root,int no){   
     28     node *p=root;   
     29     int i=0,index;    
     30     while(str[i]){   
     31         index=str[i]-'A'; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
     32         if(p->next[index]==NULL) p->next[index]=new node();    
     33         p=p->next[index];  
     34         i++;  
     35     }   
     36     p->count=no;//初始化为0,++后为1,表示是一个单词的结尾!!!!!!!!!!!!!!!!!  
     37 }   
     38 void build_ac_automation(node *root)  
     39 {  
     40     int i;  
     41     root->fail=NULL;   
     42     q[head++]=root;   
     43     while(head!=tail)  
     44     {   
     45         node *temp=q[tail++];//拿到一个节点  
     46         node *p=NULL;   
     47         for(i=0;i<26;i++)//!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
     48         {   
     49             if(temp->next[i]!=NULL)//若其i孩子非空  
     50             {   
     51                 if(temp==root) //他自己是头,其孩子的失败指针指向头  
     52                     temp->next[i]->fail=root;                   
     53                 else{ //普通节点  
     54                     p=temp->fail; //指向自己的失败指针  
     55                     while(p!=NULL)  
     56                     {    
     57                         if(p->next[i]!=NULL)//失败指针有i孩子  
     58                         {   
     59                             temp->next[i]->fail=p->next[i]; //当前节点的i孩子的失败指针指向失败指针的i孩子,然后跳出  
     60                             break;   
     61                         }   
     62                         p=p->fail; //继续找失败指针  
     63                     }   
     64                     if(p==NULL) //若失败指针为空  
     65                         temp->next[i]->fail=root; //当前节点的i孩子的失败指针指向头  
     66                 }   
     67                 q[head++]=temp->next[i];  //进去的都是定义过失败指针的,故此过程是给其孩子定义失败指针  
     68             }   
     69         }     
     70     }   
     71 }   
     72 int query(node *root)  
     73 {   
     74     int i=0,cnt=0,index,len=strlen(str);   
     75     node *p=root;    
     76     while(str[i])  
     77     {    
     78         index=str[i]-'A';  //计算孩子的位置!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
     79         if(index<0||index>25)//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
     80         {  
     81             p=root;  
     82             i++;  
     83             continue;  
     84         }  
     85         while(p->next[index]==NULL && p!=root)   
     86             p=p->fail; //若没有i孩子节点,通过失败指针找与这之前相同的有i孩子的节点  
     87         p=p->next[index]; //指向其i孩子  
     88         p=(p==NULL)?root:p;   
     89         node *temp=p;   
     90         while(temp!=root && temp->count)  
     91         {   
     92             if(temp->count)//主要是改这里!!!!!!!!!!!!!!!!!!!!!!!!!!!  
     93             {  
     94                 cnt++;  
     95                 ++biaoshi[temp->count];  
     96             }  
     97             temp=temp->fail;   
     98         }   
     99         i++;                   
    100     }      
    101     return cnt;   
    102 }   
    103 int cmp(const void *a,const void *b)  
    104 {  
    105     int *c=(int*)a,*d=(int*)b;  
    106     return *c-*d;  
    107 }  
    108 void print(int ji,int na,int n)  
    109 {  
    110   
    111     printf("web %d:",na);  
    112     for(int i=1;i<=n;++i)  
    113     {  
    114         if(biaoshi[i])  
    115         {  
    116         printf(" %d",i);  
    117         }  
    118     }  
    119     printf("
    ");  
    120 }  
    121 int main(){   
    122     int n,t,i,j=0;   
    123     while(scanf("%d",&n)!=EOF)  
    124     {    
    125         head=tail=0;   
    126         node *root=new node();   
    127         
    128         getchar();   
    129         for(i=1;i<=n;i++)  
    130         {  
    131             gets(keyword);   
    132             strcpy(chuan[i],keyword);  
    133             insert(keyword,root,i);   
    134         }   
    135         build_ac_automation(root);   
    136         memset(biaoshi,0,sizeof(biaoshi));  
    137         scanf("%s",str);  
    138         query(root);  
    139         for(i=1;i<=n;i++)  
    140         {  
    141             if(biaoshi[i])  
    142             {  
    143                 printf("%s: %d
    ",chuan[i],biaoshi[i]);  
    144             }  
    145         }  
    146         //printf("total: %d
    ",j);  
    147     }   
    148     return 0;   
    149 }  
  • 相关阅读:
    Java多态
    24系列EEPROM应用注意事项
    EEPROM读写问题
    EEPROM读写操作常见的陷阱
    MPLAB X IDE使用心得
    PIC18系列单片机I/O端口操作寄存器及应用
    IAR使用printf()函数 打印输出
    0欧电阻作用
    IAR MSP430设置合理堆栈大小(the stack pointer for stack is outside the stack range)
    MSP430教程14:MSP430单片机ADC12模块
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/8492875.html
Copyright © 2011-2022 走看看