• [hdu2896]病毒侵袭(AC自动机)


    题意:给出n个病毒和m个网站,找出每一个网站中含有的病毒种类,并按病毒编号升序输出,最后统计含有病毒的网站个数。

    每道AC自动机不同的地方就是end数组代表的意义,这里还需要加一个vis数组判断是否访问过。其他就是ASCII码可见字符为32-196 共95个字符。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=96;
     5 const int MAXN=100010;
     6 int num,ans[5],nn;
     7 bool vis[MAXN];
     8 struct Trie{//数组形式 
     9     int Next[MAXN][N],Fail[MAXN],End[MAXN],root,tot;//大小为所以匹配字符串的总和 
    10     int newnode(){//结构体内部用 
    11         for(int i=0;i<N;i++) Next[tot][i]=-1;
    12         End[tot++]=0;
    13         return tot-1;
    14     }
    15     void init(){
    16         tot=0;
    17         root=newnode();
    18     }
    19     void insert(char buf[],int x){
    20         int len=strlen(buf);
    21         int now=root;//now是temp指针 
    22         for(int i=0;i<len;i++){
    23             int k=buf[i]-32;
    24             if(Next[now][k]==-1)  Next[now][k]=newnode();//next数组代表的是下一个字符索引 
    25             now=Next[now][k];
    26         }
    27         End[now]=x;//end数组是当前字符串的个数.字典中可能有相同的单词,若只算一次,改为1. 
    28     }
    29     void build(){//构造fail指针,后缀是某些前缀 
    30         queue<int>que;
    31         Fail[root]=root;
    32         for(int i=0;i<N;i++){ 
    33             if(Next[root][i]==-1) Next[root][i]=root;
    34             else{
    35                 Fail[Next[root][i]]=root;
    36                 que.push(Next[root][i]);
    37             }
    38         } 
    39         while(!que.empty()){//bfs,会将所有的匹配子串都遍历到 
    40             int now=que.front();
    41             que.pop();
    42             for(int i=0;i<N;i++){
    43                 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i];
    44                 else{
    45                     Fail[Next[now][i]]=Next[Fail[now]][i];//fail指向最长的 
    46                     que.push(Next[now][i]);
    47                 }
    48             }
    49         }
    50     }
    51     void query(char buf[]){
    52         int len=strlen(buf),now=root;
    53         for(int i=0;i<len;i++){
    54             now=Next[now][buf[i]-32];
    55             int temp=now;
    56             while(temp!=root){
    57                 if(!vis[temp]&&End[temp]) ans[nn++]=End[temp];
    58                 vis[temp]=true;
    59                 temp=Fail[temp];
    60             }
    61         }
    62     }
    63 };
    64 
    65 Trie ac;
    66 char buf[10003];
    67 int n,m;
    68 int main(){
    69     num=0;
    70     ios::sync_with_stdio(0);
    71     ac.init();
    72     cin>>n;
    73     for(int i=1;i<=n;i++){
    74         cin>>buf;
    75         ac.insert(buf,i);
    76     }
    77     ac.build();//不要忘记build 
    78     cin>>m;
    79     for(int i=1;i<=m;i++){
    80         memset(vis,0,sizeof vis);
    81         nn=0;
    82         cin>>buf;
    83         ac.query(buf);
    84         if(nn==0) continue;
    85         sort(ans,ans+nn);
    86         cout<<"web "<<i<<":";
    87         for(int j=0;j<nn;j++){
    88             cout<<" "<<ans[j];
    89         }
    90         cout<<"
    ";
    91         num++;
    92     }
    93     cout<<"total: "<<num<<"
    ";
    94     return 0;
    95 } 
  • 相关阅读:
    406. 根据身高重建队列 vector 自定义排序
    5552. 到家的最少跳跃次数 BFS
    5602. 将 x 减到 0 的最小操作数 双指针
    Hadoop Container is running beyond memory limits code143
    1122. 数组的相对排序 自定义排序
    328. 奇偶链表 链表
    127. 单词接龙 bfs
    5600. 第 K 条最小指令 组合数学
    5548. 最小体力消耗路径 二分
    1024. 视频拼接 dp
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7506861.html
Copyright © 2020-2023  润新知