hdu 2896 AC自动机模板题

题意:给出n个模式串,再给出m个文本串

   针对每一个文本串,假如文本串中包含模式串,就total++,然后输出包含的模式串,从小到达输出编号

思路:这道题有个地方需要注意一下,题目中给出的字符不单单只有小写字母,所以我们把trie的第二维开到128

    其他地方没什么不同

    但是! 我自我感觉这样子做是会超时的,可是竟然没有超。。。

      根据数据:每一个文本串1e4,那么查询当个的复杂度为 1e4+模式串个数(这里忽略不计)*(模式串的平均长度,我们假定100)

            因此,单个查询复杂度就已经到达了1e6,然后有1000个查询。。。

      大概是学艺不精把,毕竟初学ac自动机,所以其中缘由并不清楚

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1000001;
 4 struct AC{
 5     int son[130];
 6     int flag,fail;
 7 }trie[maxn];
 8 int n,cnt;
 9 char s[maxn];
10 queue<int>q;
11 int total;
12 int match[maxn];
13 int res[maxn];
14 int book;
15 void Insert(char* s,int base)
16 {
17     int u=1,len=strlen(s);
18     for(int i=0;i<len;i++){
19         int v=s[i];
20         if(!trie[u].son[v])
21             trie[u].son[v]=++cnt;
22         u=trie[u].son[v];
23     }
24     trie[u].flag++;
25     match[u]=base;
26 }
27 void getFail()
28 {
29     for(int i=0;i<=128;i++)
30         trie[0].son[i]=1;          //初始化0的所有儿子都是1
31     q.push(1);trie[1].fail=0;               //将根压入队列
32     while(!q.empty()){
33         int u=q.front();q.pop();
34         for(int i=0;i<=128;i++){              //遍历所有儿子
35             int v=trie[u].son[i];           //处理u的i儿子的fail,这样就可以不用记父亲了
36             int Fail=trie[u].fail;          //就是fafail,trie[Fail].son[i]就是和v值相同的点
37             if(!v){
38                 trie[u].son[i]=trie[Fail].son[i];
39                 continue;
40             }  //不存在该节点,第二种情况
41             trie[v].fail=trie[Fail].son[i]; //第三种情况,直接指就可以了
42             q.push(v);                      //存在实节点才压入队列
43         }
44     }
45 }
46 int query(char* s)
47 {
48     int u=1,ans=0,len=strlen(s);
49     for(int i=0;i<len;i++){
50         int v=s[i];
51         int k=trie[u].son[v];       //跳Fail
52         while(k>1){   //经过就不统计了
53             if(trie[k].flag>0){
54                 book++;
55                 res[book]=match[k];
56             }
57             k=trie[k].fail;         //继续跳Fail
58         }
59         u=trie[u].son[v];           //到下一个儿子
60     }
61     return ans;
62 }
63 int main(){
64     cnt=1;scanf("%d",&n);
65     for(int i=1;i<=n;i++){
66         scanf("%s",s);
67         Insert(s,i);
68     }
69     getFail();
70     int T;
71     scanf("%d",&T);
72     for(int Case=1;Case<=T;Case++){
73         book=0;
74         scanf("%s",s);
75         query(s);
76         if(book) total++;
77         sort(res+1,res+1+book);
78         if(book){
79             printf("web %d: ",Case);
80             for(int i=1;i<book;i++)
81                 printf("%d ",res[i]);
82             printf("%d\n",res[book]);
83         }
84     }
85     printf("total: %d\n",total);
86     return 0;
87 }
View Code

 

  

posted @ 2020-04-09 17:44  古比  阅读(106)  评论(0编辑  收藏  举报