这个题把病毒分为了两种,一种包含可以覆盖,另一种不可以,需要分别求出包含他们的个数,可以把两种都建在一颗tire树上,在最后求得时候判断一下当前节点是属于哪种字符串,如果是不包含的需要判断一下pre[i]+len[i]<=当前位置。
注意会有重复字符串,可以先map处理一下。
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 }
时间: 2024-10-26 06:15:52