• BZOJ


    题意

    现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身)。

    题解

    首先是广义后缀自动机,就是每次将$last$归为$Root$,从而将几个后缀自动机拼在一起处理

    那么现在需要知道每个字串在$n$个母串中的出现次数,所谓字串,就是所有前缀的所有后缀,所以可以顺着前缀走,那么通过$Parent$树找后缀,一直往上跳,那么需要加一的所有后缀就是所属母串并非当前母串的那几个

    此时再整理出每个所属母串个数$Size >= K$的初始贡献,即$Len[i] - Len[Father[i]]$,反之赋$0$

    又子串为前缀的后缀,那么一个节点的贡献即为它祖先至它本身的贡献前缀和,即它所有后缀能够构成的子串数

    最后再遍历一遍前缀统计答案即可

    代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <string>
      5 #include <vector>
      6 
      7 using namespace std;
      8  
      9 typedef long long LL;
     10  
     11 const int MAXN = 6e05 + 10;
     12  
     13 int N, K;
     14 string Str[MAXN >> 2];
     15 
     16 const int Root = 1;
     17 int Tree[MAXN][30]= {0};
     18 int Father[MAXN]= {0};
     19 int Len[MAXN]= {0}, Size[MAXN]= {0};
     20 int Belong[MAXN]= {0};
     21 int last = Root, nodes = 1;
     22 void Append (int c, int bel) {
     23     int fa = last, p = ++ nodes;
     24     last = p;
     25     Len[p] = Len[fa] + 1;
     26     while (fa && ! Tree[fa][c])
     27         Tree[fa][c] = p, fa = Father[fa];
     28     if (! fa)
     29         Father[p] = 1;
     30     else {
     31         int x = Tree[fa][c];
     32         if (Len[x] == Len[fa] + 1)
     33             Father[p] = x;
     34         else {
     35             int np = ++ nodes;
     36             Len[np] = Len[fa] + 1, Father[np] = Father[x];
     37             Father[p] = Father[x] = np;
     38             memcpy (Tree[np], Tree[x], sizeof (Tree[x]));
     39             while (fa && Tree[fa][c] == x)
     40                 Tree[fa][c] = np, fa = Father[fa];
     41         }
     42     }
     43 }
     44 int Topo[MAXN];
     45 int W[MAXN]= {0};
     46 int buck[MAXN]= {0};
     47 void Merge () {
     48     for (int i = 1; i <= N; i ++) {
     49         int n = Str[i].size();
     50         int p = Root;
     51         for (int j = 0; j < n; j ++) {
     52             p = Tree[p][Str[i][j] - 'a'];
     53             int fa = p;
     54             while (fa && Belong[fa] != i) {
     55                 Size[fa] ++;
     56                 Belong[fa] = i;
     57                 fa = Father[fa];
     58             }
     59         }
     60     }
     61     for (int i = 1; i <= nodes; i ++)
     62         buck[Len[i]] ++;
     63     for (int i = 1; i <= nodes; i ++)
     64         buck[i] += buck[i - 1];
     65     for (int i = nodes; i >= 1; i --)
     66         Topo[buck[Len[i]] --] = i;
     67     for (int i = 1; i <= nodes; i ++)
     68         if (Size[i] >= K)
     69             W[i] = Len[i] - Len[Father[i]];
     70     for (int i = 1; i <= nodes; i ++)
     71         W[Topo[i]] += W[Father[Topo[i]]];
     72 }
     73  
     74 LL Answer[MAXN >> 2]= {0};
     75  
     76 int main () {
     77     scanf ("%d%d", & N, & K);
     78     for (int i = 1; i <= N; i ++) {
     79         cin >> Str[i];
     80         int n = Str[i].size();
     81         last = Root;
     82         for (int j = 0; j < n; j ++)
     83             Append (Str[i][j] - 'a', i);
     84     }
     85     Merge ();
     86     for (int i = 1; i <= N; i ++) {
     87         int n = Str[i].size();
     88         int p = Root;
     89         for (int j = 0; j < n; j ++)
     90             p = Tree[p][Str[i][j] - 'a'], Answer[i] += W[p];
     91     }
     92     for (int i = 1; i <= N; i ++) {
     93         if (i > 1)
     94             putchar (' ');
     95         printf ("%lld", Answer[i]);
     96     }
     97     puts ("");
     98  
     99     return 0;
    100 }
    101  
    102 /*
    103 3 1
    104 abc
    105 a
    106 ab
    107 */
    108 
    109 /*
    110 2 2
    111 aa
    112 aaa
    113 */
    View Code
  • 相关阅读:
    Odd sum CodeForces
    Chips CodeForces
    Secrets CodeForces
    Voting CodeForces
    Jury Meeting CodeForces
    Planning CodeForces
    Maxim Buys an Apartment CodeForces
    Chemistry in Berland CodeForces
    Monitor CodeForces
    Four Segments CodeForces
  • 原文地址:https://www.cnblogs.com/Colythme/p/10085189.html
Copyright © 2020-2023  润新知