hdu 2896 病毒侵袭

点击打开链接hdu 2896


思路:AC自动机
分析:
1 题目输入n个字符串,然后输入m个源码串。对每一个源码串要求找到里面包含了几个字符串,如果有包含则按照从小到大输出字符串的编号,否则不输出。
2 典型的ac自动机。首先利用n个字符串建立字典树并且在字典树上面求出失配指针。然后对每一个输入的源码串进行find()即可。

3 ASCLL字符表可见字符(可打印字符)从32~126


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

#define INF 0x3f3f3f3f /*这个值可以用来初始化数组*/
#define MAXN 100010
#define N 110

int n , m , sum , cnt;
int ans[3];
struct Node{
   Node* next;
   Node* child[N];
   int number;/*标记编号*/
   int pos;/*标记有没有被用过*/
};
Node node[MAXN];
Node *root;
queue<Node*>q;

Node* newNode(){
    node[cnt].next = NULL;
    node[cnt].number = 0;
    node[cnt].pos = 0;
    for(int i = 0 ; i < N ; i++)
        node[cnt].child[i] = NULL;
    return &node[cnt++];
}

void insert(char *str , int x){
    Node *p = root;
    int len = strlen(str);

    for(int i = 0 ; i < len ; i++){
       int num = str[i]-32;
       if(p->child[num] == NULL)
         p->child[num] = newNode();
       p = p->child[num];
    }
    p->number = x;
}

void getNext(){
    
    while(!q.empty())
       q.pop();
    q.push(root);
    root->next = NULL;

    while(!q.empty()){
       Node *p = q.front();
       q.pop();

       for(int i = 0 ; i < N ; i++){
          if(p->child[i]){
            q.push(p->child[i]);
            Node *tmp = p->next;

            while(tmp){
              if(tmp->child[i]){
                p->child[i]->next = tmp->child[i];
                break;
              }
              tmp = tmp->next;
            }
            if(tmp == NULL)
              p->child[i]->next = root;
          }
       }
    }
}

void find(char *str , int x){
    
    int len = strlen(str);
    int pos = 0;
    Node *p = root;

    for(int i = 0 ; i < len ; i++){
       int num = str[i]-32;
       while(p->child[num] == NULL && p != root)
           p = p->next;
       if(p->child[num]){
           p = p->child[num];
           Node *tmp = p;
           while(tmp){
              if(tmp->number){
                if(tmp->pos != x){/*如果没有被用过那么保存到ans数组里面*/
                  ans[pos++] = tmp->number;
                  tmp->pos++;
                }
              }
              tmp = tmp->next;       
           }
       }
    }
}

int main(){
   char str[MAXN];
   while(scanf("%d%*c" , &n) != EOF){
      sum = cnt = 0;
      root = newNode();
       
      for(int i = 1 ; i <= n ; i++){
         gets(str);
         insert(str , i);
      }
      getNext();
      scanf("%d%*c" , &m);
      for(int i = 1 ; i <= m ; i++){
         gets(str);
         memset(ans , INF , sizeof(ans));/*初始化为INF*/
         find(str , i);
         if(ans[0] == INF)
            continue;
         printf("web %d:" , i);
         sort(ans , ans+3);/*排序*/
         for(int j = 0 ; j < 3 ; j++){
            if(ans[j] == INF)
              break;
            printf(" %d" , ans[j]);
         }
         printf("\n");
         sum++;
      }
      printf("total: %d\n" , sum);
   }
   return 0;
}



你可能感兴趣的:(hdu 2896 病毒侵袭)