• bzoj 3473 字符串


    题目传送门

      传送门

    题目大意

      给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串

      先用奇怪的字符把所有字符串连接起来。

      建后缀树,数每个节点的子树内包含多少属于不同串的后缀。

      数这个东西,可以将每个串的后缀(被奇怪的字符分割开的地方认为它属于不同后缀)按dfs序排序,然后简单容斥就能统计出来。

      对于每个后缀,有贡献的是一个前缀,然后直接统计就行了。

    Code

      1 /**
      2  * bzoj
      3  * Problem#3473
      4  * Accepted
      5  * Time: 788ms
      6  * Memory: 41208k
      7  */
      8 #include <iostream>
      9 #include <cstdlib>
     10 #include <cstring>
     11 #include <cstdio>
     12 #include <vector>
     13 #include <cmath>
     14 using namespace std;
     15 typedef bool boolean;
     16 
     17 template <typename T>
     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 << '
    ';
     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<int, int>
    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 }
  • 相关阅读:
    2020.9.21
    企业应用架构模式003——对象-关系结构模式
    企业应用架构模式002
    企业应用架构模式001
    代码大全003/
    代码大全002/
    每日总结
    数论必刷题
    Tarjan求割点(割顶) 割边(桥)
    Luogu 2018 秋令营 Test 2
  • 原文地址:https://www.cnblogs.com/yyf0309/p/10232222.html
Copyright © 2020-2023  润新知