hdu2896(ac自动机)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896

 

题意: 中文题诶~

 

思路: ac自动机

这里要求记录匹配的模式串的编号, 不过题目中说明了不同模式串对应的编号是不同的, 所以可以直接用 end 数组记录编号即可, 然后与主串匹配成功的标记一下即可.

 

代码:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <queue>
  5 using namespace std;
  6 
  7 const int MAXN = 500 * 200 + 10;
  8 int sol[510];
  9 
 10 struct Trie{
 11     int next[MAXN][128], fail[MAXN], end[MAXN];
 12     int root, L;
 13     int newnode(){//初始化字典树节点
 14         for(int i = 0; i < 128; i++){
 15             next[L][i] = -1;
 16         }
 17         end[L++] = 0;
 18         return L - 1;
 19     }
 20     void init(){//初始化字典树根节点
 21         L = 0;
 22         root = newnode();
 23     }
 24     void insert(char buf[], int id){//往字典树中插入一个单词
 25         int len = strlen(buf);
 26         int now = root;
 27         for(int i = 0; i < len; i++){
 28             if(next[now][buf[i]] == -1) next[now][buf[i]] = newnode();
 29             now = next[now][buf[i]];
 30         }
 31         end[now] = id;//记录编号
 32     }
 33     void build(){ //构造fail数组
 34         queue<int> Q;
 35         fail[root] = root;
 36         for(int i = 0; i < 128; i++){
 37             if(next[root][i] == -1) next[root][i] = root;
 38             else{
 39                 fail[next[root][i]] = root;
 40                 Q.push(next[root][i]);
 41             }
 42         }
 43         while(!Q.empty()){
 44             int now = Q.front();
 45             Q.pop();
 46             for(int i = 0; i < 128; i++)
 47             if(next[now][i] == -1) next[now][i] = next[fail[now]][i];
 48             else{
 49                 fail[next[now][i]] = next[fail[now]][i];
 50                 Q.push(next[now][i]);
 51             }
 52         }
 53     }
 54     bool query(char buf[]){
 55         int len = strlen(buf);
 56         int now = root;
 57         bool flag = false;
 58         for(int i = 0; i < len; i++){
 59             now = next[now][buf[i]];
 60             int temp = now;
 61             while(temp != root){
 62                 if(end[temp]){
 63                     sol[end[temp]] = 1;
 64                     flag = true;
 65                 }
 66                 temp = fail[temp];
 67             }
 68         }
 69         return flag;
 70     }
 71     void debug(){
 72         for(int i = 0; i < L; i++){
 73             printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
 74             for(int j = 0; j < 26; j++){
 75                 printf("%2d",next[i][j]);
 76             }
 77             printf("]\n");
 78         }
 79     }
 80 };
 81 
 82 Trie ac;
 83 char buf[MAXN];
 84 
 85 int main(void){
 86     int n, m;
 87     while(~scanf("%d", &n)){
 88         ac.init();
 89         int tot = 0;
 90         for(int i = 1; i <= n; i++){
 91             scanf("%s", buf);
 92             ac.insert(buf, i);
 93         }
 94         ac.build();
 95         scanf("%d", &m);
 96         for(int i = 1; i <= m; i++){
 97             scanf("%s", buf);
 98             bool flag = ac.query(buf);
 99             if(flag){
100                 tot += 1;
101                 printf("web %d:", i);
102                 for(int j = 1; j <= n; j++){
103                     if(sol[j]){
104                         sol[j] = 0;
105                         printf(" %d", j);
106                     }
107                 }
108                 puts("");
109             }
110         }
111         printf("total: %d\n", tot);
112     }
113     return 0;
114 }
View Code

 

posted @ 2017-08-24 11:08  geloutingyu  阅读(317)  评论(0编辑  收藏  举报