• HDU 2896 病毒侵袭【AC自动机】



    http://acm.hdu.edu.cn/showproblem.php?pid=2896
    HDU 2896 病毒侵袭
    大意:
    有n种病毒,编码已知。有m个网站源码,求带病毒的网站个数以及其对应的病毒
    Sample Input
    3
    aaa
    bbb
    ccc
    2
    aaabbbccc
    bbaacc
     

    Sample Output
    web 1: 1 2 3
    total: 1

    hint:有3种病毒,编码分别为
    aaa
    bbb
    ccc
    2个网站,其中网站1包含了编号1,2,3病毒关键字

    分析:
    AC自动机。

    PS:学长出的题,算是模板题吧。。。。贴上来,备着O(∩_∩)O~

    View Code
    1 #include<iostream>
    2 #include<queue>
    3 using namespace std;
    4
    5 //子树节点是在插入时new的,
    6 //寻找失配指针中使用的队列是直接调用STL的
    7 const int kind = 100;//子树个数,因可见ASCII码为32-126,少于100个
    8 bool visited[500+10];//记录当前病毒是否被访问
    9 int ansid[4];
    10 int ansnum;
    11 struct node
    12 {
    13 node *fail;
    14 node *next[kind];
    15 int count;//记录当前前缀是完整单词出现的个数
    16 int id;//记录病毒编号
    17 node()
    18 {
    19 fail = NULL;
    20 count = 0;
    21 memset(next,NULL,sizeof(next));
    22 }
    23 };//寻找失配指针时需要用到的队列
    24
    25 char keyword[201+10];//关键字
    26 char str[80000];//主串
    27 void insert(char *str,node *root,int id)
    28 {
    29 node *p=root;
    30 int i=0,index;
    31 while(str[i])
    32 {
    33 index = str[i]-31;
    34 if(p->next[index]==NULL)
    35 p->next[index]=new node();
    36
    37 p=p->next[index];
    38 i++;
    39 }
    40 p->count++;
    41 p->id = id;
    42 }
    43
    44 //寻找失败指针
    45 void build_ac_automation(node *root)
    46 {
    47 int i;
    48 queue<node *>Q;
    49 root->fail = NULL;
    50 Q.push(root);
    51 while(!Q.empty())
    52 {
    53 node *temp = Q.front();//q[head++];//取队首元素
    54 Q.pop();
    55 node *p = NULL;
    56 for(i=0;i<kind;i++)
    57 {
    58 if(temp->next[i]!=NULL)//寻找当前子树的失败指针
    59 {
    60 p = temp->fail;
    61 while(p!=NULL)
    62 {
    63 if(p->next[i]!=NULL)//找到失败指针
    64 {
    65 temp->next[i]->fail = p->next[i];
    66 break;
    67 }
    68 p = p->fail;
    69 }
    70
    71 if(p==NULL)//无法获取,当前子树的失败指针为根
    72 temp->next[i]->fail = root;
    73
    74 Q.push(temp->next[i]);
    75 }
    76 }
    77 }
    78 }
    79
    80 //询问str中包含n个关键字中多少种
    81 void query(node *root)
    82 {
    83 int i = 0,cnt = 0,index,len;
    84 ansnum = 0;
    85 memset(visited,false,sizeof(visited));
    86 len = strlen(str);
    87 node *p = root;
    88 while(str[i])
    89 {
    90 index = str[i]-31;
    91 while(p->next[index]==NULL&&p!=root)//失配
    92 p=p->fail;
    93 p=p->next[index];
    94 if(p==NULL)//失配指针为根
    95 p = root;
    96
    97 node *temp = p;
    98 while(temp!=root)//寻找到当前位置为止是否出现病毒关键字
    99 {
    100 if(temp->count!=0&&visited[temp->id]==false)
    101 {
    102 visited[temp->id]=true;
    103 ansid[ansnum++]=temp->id;
    104 if(ansnum==3)return;
    105 }
    106
    107 temp=temp->fail;
    108 }
    109 i++;
    110 }
    111 }
    112 int main()
    113 {
    114 int n,t;
    115 while(scanf("%d",&n)!=EOF)
    116 {
    117
    118 node *root = new node();
    119 getchar();
    120 int id = 0;
    121 while(n--)
    122 {
    123
    124 gets(keyword);
    125 insert(keyword,root,++id);
    126 }
    127
    128 //求失败指针
    129 build_ac_automation(root);
    130 int m;
    131 scanf("%d",&m);
    132 id=0;
    133 int total = 0;
    134 while(m--)
    135 {
    136 scanf("%s",str);
    137 query(root);
    138 id++;
    139 if(ansnum!=0)
    140 {
    141 total++;
    142 printf("web %d:",id);
    143 sort(ansid,ansid+ansnum);//不要忘记排序,错在这里就郁闷了o(>﹏<)o
    144 for(int i=0;i<ansnum;i++)
    145 printf(" %d",ansid[i]);
    146 printf("\n");
    147 }
    148 }
    149 printf("total: %d\n",total);
    150 }
    151 return 0;
    152 }
  • 相关阅读:
    Ubuntu解压缩命令
    小语种优化策略
    外贸seo常用Zen Cart数据库mysql批量执行命令
    ASP Request.ServerVariables
    centos linux 下 crontab e 命令插入及保存
    AJAX 传值给后台
    partial class
    Jquery 实现弹出层
    abstract class
    SQL锁表
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1986482.html
Copyright © 2020-2023  润新知