zoj3228Searching the String(ac自动机)

时间:2022-03-17 05:59:34

链接

这个题把病毒分为了两种,一种包含可以覆盖,另一种不可以,需要分别求出包含他们的个数,可以把两种都建在一颗tire树上,在最后求得时候判断一下当前节点是属于哪种字符串,如果是不包含的需要判断一下pre[i]+len[i]<=当前位置。

注意会有重复字符串,可以先map处理一下。

zoj3228Searching the String(ac自动机)zoj3228Searching the String(ac自动机)
  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 #include<string>
 11 #include<map>
 12 using namespace std;
 13 #define N 600110
 14 #define LL long long
 15 #define INF 0xfffffff
 16 const double eps = 1e-8;
 17 const double pi = acos(-1.0);
 18 const double inf = ~0u>>2;
 19 const int child_num = 26;
 20 char vir[10];
 21 char s[N/6];
 22 int o[N/6],len[N/6],ans[N/6][2],po[N/6];
 23 int cc[N/6];
 24 map<string,int>f;
 25 vector<int>ed[N/6];
 26 class AC
 27 {
 28     private:
 29     int ch[N][child_num];
 30     int fail[N];
 31     int Q[N];
 32     int val[N];
 33     int sz;
 34     int id[128];
 35     public:
 36     void init()
 37     {
 38         fail[0] = 0;
 39         for(int i = 0 ;i < child_num ; i++)
 40         id[i+'a'] = i;
 41     }
 42     void reset()
 43     {
 44         memset(ch[0],0,sizeof(ch[0]));
 45         memset(val,0,sizeof(val));
 46         sz = 1;
 47     }
 48     void insert(char *a,int key)
 49     {
 50         int p = 0;
 51         for(; *a ; a++)
 52         {
 53             int d= id[*a];
 54             if(ch[p][d]==0)
 55             {
 56                 memset(ch[sz],0,sizeof(ch[sz]));
 57                 ch[p][d] = sz++;
 58             }
 59             p = ch[p][d];
 60         }
 61         val[p] = key;
 62     }
 63     void construct()
 64     {
 65         int i,head=0,tail = 0;
 66         for(i = 0; i  < child_num ;i++)
 67         {
 68             if(ch[0][i])
 69             {
 70                 fail[ch[0][i]] = 0;
 71                 Q[tail++] = ch[0][i];
 72             }
 73         }
 74         while(head!=tail)
 75         {
 76             int u = Q[head++];
 77             for(i = 0; i < child_num ; i++)
 78             {
 79                 if(ch[u][i])
 80                 {
 81                     fail[ch[u][i]] = ch[fail[u]][i];
 82                     Q[tail++] = ch[u][i];
 83                 }
 84                 else ch[u][i] = ch[fail[u]][i];
 85             }
 86         }
 87     }
 88     void work(int m,int kk,int g)
 89     {
 90         memset(ans,0,sizeof(ans));
 91         memset(po,-1,sizeof(po));
 92         int p = 0,i,k = strlen(s);
 93         for(i = 0 ; i < k ; i++)
 94         {
 95             int d = id[s[i]];
 96             p = ch[p][d];
 97             int tmp = p;
 98             while(tmp)
 99             {
100                 int v = val[tmp];
101                 ans[v][0]++;
102                 if(po[v]+len[v]<=i)
103                 {
104                     po[v] = i;
105                     ans[v][1]++;
106                 }
107                 tmp = fail[tmp];
108             }
109         }
110         for(i = 1; i <= g ; i++)
111         {
112             for(int j = 0; j < ed[i].size() ; j++)
113             {
114                 int v = ed[i][j];
115                 if(o[v]) cc[v] = ans[i][1];
116                 else cc[v] = ans[i][0];
117             }
118         }
119         printf("Case %d\n",kk);
120         for(i = 1 ; i <= m ;i++)
121         printf("%d\n",cc[i]);
122         puts("");
123     }
124 }ac;
125 int main()
126 {
127     int i,m,kk=0;
128     ac.init();
129     while(scanf("%s",s)!=EOF)
130     {
131         ac.reset();
132         f.clear();
133         scanf("%d",&m);
134         int g = 0;
135         for(i = 1 ; i <= m; i++)
136         ed[i].clear();
137         for(i = 1;i <= m ;i++)
138         {
139             scanf("%d%s",&o[i],vir);
140             if(!f[vir])
141             {
142                 f[vir] = (++g);
143                 ac.insert(vir,g);
144                 len[g] = strlen(vir);
145             }
146             ed[f[vir]].push_back(i);
147         }
148         ac.construct();
149         kk++;
150         ac.work(m,kk,g);
151     }
152     return 0;
153 }
View Code