解:对被包含的那些串建AC自动机。
每次加一个串,就在AC自动机上面跑,可知能够跑到一些节点。
这些节点都是一些前缀的形式,我们跳fail树就是跳后缀,这样就能够得到所有能匹配的子串。
我们分别对AC自动机中的每个串计算答案。
就是要求一些节点到根路径的并集,并对其权值 + 1。查询就查对应节点。
然后有个trick就是lca处 - 1,节点处 + 1,然后求子树和。、
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 3 const int N = 100010, M = 2000010; 4 5 struct Edge { 6 int nex, v; 7 }edge[M]; int tp; 8 9 int tr[M][26], fail[M], tot = 1, n, ed[N]; 10 std::queue<int> Q; 11 char str[N]; 12 int e[M], pos[M], siz[M], num, ST[M << 1][22], d[M], stk[M], pw[M << 1], top, pos2[M << 1], num2; 13 14 inline void add(int x, int y) { 15 tp++; 16 edge[tp].v = y; 17 edge[tp].nex = e[x]; 18 e[x] = tp; 19 return; 20 } 21 22 void DFS(int x) { 23 pos[x] = ++num; 24 pos2[x] = ++num2; 25 ST[num2][0] = x; 26 siz[x] = 1; 27 for(int i = e[x]; i; i = edge[i].nex) { 28 int y = edge[i].v; 29 d[y] = d[x] + 1; 30 DFS(y); 31 ST[++num2][0] = x; 32 siz[x] += siz[y]; 33 } 34 return; 35 } 36 37 inline void prework() { 38 for(int i = 2; i <= num2; i++) { 39 pw[i] = pw[i >> 1] + 1; 40 } 41 for(int j = 1; j <= pw[num2]; j++) { 42 for(int i = 1; i + (1 << j) - 1 <= num2; i++) { 43 if(d[ST[i][j - 1]] < d[ST[i + (1 << (j - 1))][j - 1]]) 44 ST[i][j] = ST[i][j - 1]; 45 else 46 ST[i][j] = ST[i + (1 << (j - 1))][j - 1]; 47 } 48 } 49 /*for(int j = 0; j <= pw[num2]; j++) { 50 printf("j = %d : ", j); 51 for(int i = 1; i + (1 << j) - 1 <= num2; i++) { 52 printf("%d ", ST[i][j]); 53 } 54 puts(""); 55 }*/ 56 return; 57 } 58 59 inline bool cmp(const int &a, const int &b) { 60 return pos[a] < pos[b]; 61 } 62 63 inline int lca(int x, int y) { 64 //printf("lca : %d %d = ", x, y); 65 x = pos2[x]; y = pos2[y]; 66 if(x > y) std::swap(x, y); 67 int t = pw[y - x + 1]; 68 if(d[ST[x][t]] < d[ST[y - (1 << t) + 1][t]]) 69 return ST[x][t]; 70 //{ printf("%d ", ST[x][t]); return ST[x][t]; } 71 else 72 return ST[y - (1 << t) + 1][t]; 73 //{ printf("%d ", ST[y - (1 << t) + 1][t]); return ST[y - (1 << t) + 1][t]; } 74 } 75 76 namespace ta { 77 int ta[M]; 78 inline void add(int x, int v) { 79 for(int i = x; i <= tot; i += i & (-i)) { 80 ta[i] += v; 81 } 82 return; 83 } 84 inline int getSum(int x) { 85 int ans = 0; 86 for(int i = x; i >= 1; i -= i & (-i)) { 87 ans += ta[i]; 88 } 89 return ans; 90 } 91 inline int ask(int l, int r) { 92 return getSum(r) - getSum(l - 1); 93 } 94 } 95 96 inline void insert(int id) { 97 int n = strlen(str), p = 1; 98 for(int i = 0; i < n; i++) { 99 int f = str[i] - 'a'; 100 if(!tr[p][f]) { 101 tr[p][f] = ++tot; 102 } 103 p = tr[p][f]; 104 } 105 ed[id] = p; 106 return; 107 } 108 109 inline void BFS() { 110 Q.push(1); 111 fail[1] = 1; 112 while(!Q.empty()) { 113 int x = Q.front(); 114 Q.pop(); 115 for(int f = 0; f < 26; f++) { 116 if(!tr[x][f]) continue; 117 int y = tr[x][f], j = fail[x]; 118 while(j != 1 && !tr[j][f]) { 119 j = fail[j]; 120 } 121 if(x != 1 && tr[j][f]) { 122 j = tr[j][f]; 123 } 124 fail[y] = j; 125 Q.push(y); 126 } 127 } 128 return; 129 } 130 131 inline void add() { 132 int n = strlen(str), p = 1; 133 top = 0; 134 for(int i = 0; i < n; i++) { 135 int f = (str[i]) - 'a'; 136 while(p != 1 && !tr[p][f]) p = fail[p]; 137 if(tr[p][f]) p = tr[p][f]; 138 if(p > 1) stk[++top] = p; 139 } 140 if(!top) return; 141 std::sort(stk + 1, stk + top + 1, cmp); 142 top = std::unique(stk + 1, stk + top + 1) - stk - 1; 143 for(int i = 1; i <= top; i++) { 144 ta::add(pos[stk[i]], 1); 145 if(i < top) { 146 int z = lca(stk[i], stk[i + 1]); 147 ta::add(pos[z], -1); 148 } 149 } 150 return; 151 } 152 153 inline int ask(int x) { 154 return ta::ask(pos[x], pos[x] + siz[x] - 1); 155 } 156 157 int main() { 158 int m; 159 scanf("%d", &n); 160 for(int i = 1; i <= n; i++) { 161 scanf("%s", str); 162 insert(i); 163 } 164 BFS(); 165 /// 166 for(int i = 2; i <= tot; i++) { 167 add(fail[i], i); 168 //printf("add %d %d ", fail[i], i); 169 } 170 d[1] = 1; 171 DFS(1); 172 prework(); 173 174 scanf("%d", &m); 175 for(int i = 1, f, x; i <= m; i++) { 176 scanf("%d", &f); 177 if(f == 1) { 178 scanf("%s", str); 179 add(); 180 } 181 else { 182 scanf("%d", &x); 183 printf("%d ", ask(ed[x])); 184 } 185 } 186 return 0; 187 }