题目传送门
传送门
题目大意
给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串
先用奇怪的字符把所有字符串连接起来。
建后缀树,数每个节点的子树内包含多少属于不同串的后缀。
数这个东西,可以将每个串的后缀(被奇怪的字符分割开的地方认为它属于不同后缀)按dfs序排序,然后简单容斥就能统计出来。
对于每个后缀,有贡献的是一个前缀,然后直接统计就行了。
Code
1 /** 2 * bzoj 3 * Problem#3473 4 * Accepted 5 * Time: 788ms 6 * Memory: 41208k 7 */ 8 #include9 #include 10 #include 11 #include 12 #include 13 #include 14 using namespace std; 15 typedef bool boolean; 16 17 template 18 void pfill(T* pst, const T* ped, T val) { 19 for ( ; pst != ped; *(pst++) = val); 20 } 21 22 const int N = 2e5 + 5; 23 const int bzmax = 19; 24 25 typedef class SparseTable { 26 public: 27 int n; 28 int *ar; 29 int log2[N]; 30 int f[N][bzmax]; 31 32 SparseTable() { } 33 34 void init(int n, int* ar) { 35 this->n = n; 36 this->ar = ar; 37 log2[1] = 0; 38 for (int i = 2; i <= n; i++) 39 log2[i] = log2[i >> 1] + 1; 40 for (int i = 0; i < n; i++) 41 f[i][0] = ar[i]; 42 for (int j = 1; j < bzmax; j++) 43 for (int i = 0; i + (1 << j) - 1 < n; i++) 44 f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); 45 } 46 47 int query(int l, int r) { 48 int d = log2[r - l + 1]; 49 // int rt = min(f[l][d], f[r - (1 << d) + 1][d]); 50 // cerr << l << " " << r << " " << rt << '\n'; 51 return min(f[l][d], f[r - (1 << d) + 1][d]); 52 } 53 }SparseTable; 54 55 typedef class Pair3 { 56 public: 57 int x, y, id; 58 59 Pair3() { } 60 Pair3(int x, int y, int id):x(x), y(y), id(id) { } 61 }Pair3; 62 63 typedef class SuffixArray { 64 protected: 65 Pair3 T1[N], T2[N]; 66 int cnt[N]; 67 68 public: 69 int n; 70 char *str; 71 int sa[N], rk[N], hei[N]; 72 SparseTable st; 73 74 void set(int n, char* str) { 75 this->n = n; 76 this->str = str; 77 memset(sa, 0, sizeof(sa)); 78 memset(rk, 0, sizeof(rk)); 79 memset(hei, 0, sizeof(hei)); 80 } 81 82 void radix_sort(Pair3* x, Pair3* y) { 83 int m = max(n, 256); 84 memset(cnt, 0, sizeof(int) * m); 85 for (int i = 0; i < n; i++) 86 cnt[x[i].y]++; 87 for (int i = 1; i < m; i++) 88 cnt[i] += cnt[i - 1]; 89 for (int i = 0; i < n; i++) 90 y[--cnt[x[i].y]] = x[i]; 91 92 memset(cnt, 0, sizeof(int) * m); 93 for (int i = 0; i < n; i++) 94 cnt[y[i].x]++; 95 for (int i = 1; i < m; i++) 96 cnt[i] += cnt[i - 1]; 97 for (int i = n - 1; ~i; i--) 98 x[--cnt[y[i].x]] = y[i]; 99 } 100 101 void build() { 102 for (int i = 0; i < n; i++) 103 rk[i] = str[i]; 104 for (int k = 1; k <= n; k <<= 1) { 105 for (int i = 0; i + k < n; i++) 106 T1[i] = Pair3(rk[i], rk[i + k], i); 107 for (int i = n - k; i < n; i++) 108 T1[i] = Pair3(rk[i], 0, i); 109 radix_sort(T1, T2); 110 int diff = 1; 111 rk[T1[0].id] = 1; 112 for (int i = 1; i < n; i++) 113 rk[T1[i].id] = (T1[i].x == T1[i - 1].x && T1[i].y == T1[i - 1].y) ? (diff) : (++diff); 114 if (diff == n) 115 break; 116 } 117 for (int i = 0; i < n; i++) 118 sa[--rk[i]] = i; 119 } 120 121 void get_height() { 122 for (int i = 0, j, k = 0; i < n; i++, (k) ? (k--) : (0)) { 123 if (rk[i]) { 124 j = sa[rk[i] - 1]; 125 while (i + k < n && j + k < n && str[i + k] == str[j + k]) k++; 126 hei[rk[i]] = k; 127 } 128 } 129 } 130 131 void init_st() { 132 st.init(n, hei); 133 } 134 135 int lcp(int x1, int x2) { 136 if (x1 == x2) 137 return n - x1 + 1; 138 x1 = rk[x1], x2 = rk[x2]; 139 if (x1 > x2) 140 swap(x1, x2); 141 return st.query(x1 + 1, x2); 142 } 143 144 int compare(int l1, int r1, int l2, int r2) { 145 int len_lcp = lcp(l1, l2); 146 int len1 = r1 - l1 + 1, len2= r2 - l2 + 1; 147 if (len_lcp >= len1 && len_lcp >= len2) 148 return 0; 149 if (len_lcp < len1 && len_lcp < len2) 150 return (str[l1 + len_lcp] < str[l2 + len_lcp]) ? (-1) : (1); 151 return (len_lcp >= len1) ? (-1) : (1); 152 } 153 154 int query(int u, int v) { // u, v -> sa 155 if (u == v) 156 return n - sa[u]; 157 return st.query(u + 1, v); 158 } 159 160 const int& operator [] (int p) { 161 return sa[p]; 162 } 163 164 const int& operator () (int p) { 165 return hei[p]; 166 } 167 } SuffixArray; 168 169 typedef class IndexedTree { 170 public: 171 int s; 172 int *a; 173 174 IndexedTree() { } 175 IndexedTree(int n) : s(n) { 176 a = new int[(s + 1)]; 177 pfill(a + 1, a + n + 1, 0); 178 } 179 ~IndexedTree() { 180 delete[] a; 181 } 182 183 void add(int idx, int val) { 184 for ( ; idx <= s; idx += (idx & (-idx))) 185 a[idx] += val; 186 } 187 188 int query(int idx) { 189 int rt = 0; 190 for ( ; idx; idx -= (idx & (-idx))) 191 rt += a[idx]; 192 return rt; 193 } 194 195 int query(int l, int r) { 196 return query(r) - query(l - 1); 197 } 198 } IndexedTree; 199 200 typedef class Graph { 201 protected: 202 int dfs_clock; 203 public: 204 vector<int>* g; 205 int *fa; 206 int *in, *out; 207 int *sz, *zson; 208 int *dep, *top; 209 210 Graph() { } 211 Graph(vector<int>* g, int n) : dfs_clock(0), g(g) { 212 fa = new int[(n + 1)]; 213 in = new int[(n + 1)]; 214 out = new int[(n + 1)]; 215 sz = new int[(n + 1)]; 216 zson = new int[(n + 1)]; 217 dep = new int[(n + 1)]; 218 top = new int[(n + 1)]; 219 dfs1(1, 0); 220 dfs2(1, true); 221 } 222 ~Graph() { 223 #define rem(__) delete[] __; 224 rem(fa) rem(in) rem(out) rem(sz) rem(zson) rem(dep) rem(top) 225 } 226 227 void dfs1(int p, int fa) { 228 dep[p] = ((fa) ? (dep[fa] + 1) : (1)); 229 in[p] = ++dfs_clock; 230 this->fa[p] = fa; 231 sz[p] = 1; 232 int mx = -1, id = -1, e; 233 for (unsigned i = 0; i < g[p].size(); i++) { 234 e = g[p][i]; 235 dfs1(e, p); 236 sz[p] += sz[e]; 237 if (sz[e] > mx) 238 mx = sz[e], id = e; 239 } 240 out[p] = dfs_clock; 241 zson[p] = id; 242 } 243 244 void dfs2(int p, boolean ontop) { 245 top[p] = ((ontop) ? (p) : (top[fa[p]])); 246 if (~zson[p]) 247 dfs2(zson[p], false); 248 for (int i = 0, e; i < (signed) g[p].size(); i++) { 249 e = g[p][i]; 250 if (e == zson[p]) 251 continue; 252 dfs2(e, true); 253 } 254 } 255 256 int lca(int u, int v) { 257 while (top[u] ^ top[v]) { 258 if (dep[top[u]] < dep[top[v]]) 259 swap(u, v); 260 u = fa[top[u]]; 261 } 262 return (dep[u] < dep[v]) ? (u) : (v); 263 } 264 } Graph; 265 266 #define pii pair 267 268 int n, L, K; 269 int id[N]; 270 char str[N]; 271 SuffixArray sa; 272 int endp[N >> 1]; 273 char _str[N >> 1]; 274 vector<int> endpos[N >> 1]; 275 276 inline void init() { 277 L = 0; 278 scanf("%d%d", &n, &K); 279 for (int i = 1; i <= n; i++) { 280 scanf("%s", _str); 281 if (i > 1) { 282 id[L] = -1; 283 str[L] = '#'; //"!@#$%^&*()-+"[i % 11]; 284 L += 1; 285 } 286 for (char* p = _str; *p; p++) { 287 id[L] = i; 288 str[L] = *p; 289 L++; 290 } 291 endp[i] = L; 292 } 293 sa.set(L, str); 294 sa.build(); 295 sa.get_height(); 296 sa.init_st(); 297 } 298 299 int cnt_node; 300 vector<int> g[N << 1]; 301 int d[N << 1]; 302 303 int build_suffix_tree(int l, int r) { 304 int curid = ++cnt_node; 305 d[curid] = sa.query(l, r); 306 if (l == r) { 307 int p = sa[l]; 308 if (id[p] > 0) 309 endpos[id[p]].push_back(curid); 310 return curid; 311 } 312 for (int p = l, j, L, R, mid; p <= r; p = j + 1) { 313 L = p, R = r; 314 char x = str[sa[p] + d[curid]]; 315 while (L <= R) { 316 mid = (L + R) >> 1; 317 if (str[sa[mid] + d[curid]] == x) 318 L = mid + 1; 319 else 320 R = mid - 1; 321 } 322 j = L - 1; 323 L = build_suffix_tree(p, j); 324 g[curid].push_back(L); 325 } 326 return curid; 327 } 328 329 int res[N << 1]; 330 void dfs(int p, Graph& G, IndexedTree& it) { 331 res[p] = (it.query(G.in[p], G.out[p]) >= K) ? (d[p]) : (res[G.fa[p]]); 332 for (int i = 0; i < (signed) g[p].size(); i++) { 333 dfs(g[p][i], G, it); 334 } 335 } 336 337 inline void solve() { 338 while (cnt_node) 339 g[cnt_node--].clear(); 340 build_suffix_tree(0, L - 1); 341 342 IndexedTree it (cnt_node); 343 Graph graph (g, cnt_node); 344 for (int i = 1; i <= n; i++) { 345 it.add(graph.in[endpos[i][0]], 1); 346 for (int j = 1; j < (signed) endpos[i].size(); j++) { 347 it.add(graph.in[endpos[i][j]], 1); 348 int g = graph.lca(endpos[i][j], endpos[i][j - 1]); 349 it.add(graph.in[g], -1); 350 } 351 } 352 353 dfs(1, graph, it); 354 for (int i = 1, p, l; i <= n; i++) { 355 long long ans = 0; 356 for (int j = 0; j < (signed) endpos[i].size(); j++) { 357 p = endpos[i][j], l = d[p]; 358 ans += min(endp[i] - (L - l), res[p]); 359 } 360 printf("%lld ", ans); 361 } 362 } 363 364 int main() { 365 init(); 366 solve(); 367 return 0; 368 }