zoukankan      html  css  js  c++  java
  • BZOJ 3998 [TJOI 2015] 弦论 解题报告

    这是一道后缀自动机经典题目。

    对于 $t=0$ 的情况:每个节点都代表一个子串,所以我们给每个节点的 $Size$ 都记为 $1$,

    对于 $t=1$ 的情况:我们只给 $last$ 节点的 $Size$ 记为 $1$,因为新建的虚拟节点并不能给子串数目带来贡献。然后再建出 $pre$ 指针树,每个串的出现次数就是其在 $pre$ 指针树上的子树的 $Size$ 和。

    然后我们进行拓扑图 Dp, $Dp[u]$ 表示从 $u$ 号节点往后走会有多少种子串,转移的话:

    $$Dp[u] = sum_{i=0}^{26}Dp[Son[u][i]] + Size[u]$$

    然后再进行一次深搜就可以了。。

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 using namespace std;
      7 typedef long long LL;
      8 #define N 500000 + 5
      9 
     10 int n, t, k, cnt, tot, last;
     11 int Head[N << 1], q[N << 1];
     12 LL Size[N << 1];
     13 bool Vis[N << 1];
     14 char s[N];
     15 
     16 struct Edge
     17 {
     18     int next, node;
     19 }E[N << 1];
     20 
     21 struct Suffix_Automation
     22 {
     23     int pre, step, son[26];
     24 }h[N << 1];
     25 
     26 inline void addedge(int u, int v)
     27 {
     28     E[++ cnt].next = Head[u];
     29     Head[u] = cnt;
     30     E[cnt].node = v;
     31 }
     32 
     33 inline void addchar(char ch)
     34 {
     35     int np = ++ tot, p = last, j = ch - 'a';
     36     h[np].step = h[p].step + 1;
     37     Size[np] = 1;
     38     for (; p && !h[p].son[j]; p = h[p].pre)
     39         h[p].son[j] = np;
     40     if (!p && !h[p].son[j])
     41         h[p].son[j] = np, h[np].pre = p;
     42     else
     43     {
     44         int q = h[p].son[j];
     45         if (h[q].step == h[p].step + 1)
     46             h[np].pre = q;
     47         else
     48         {
     49             int nq = ++ tot;
     50             h[nq].step = h[p].step + 1;
     51             Size[nq] = t ? 0 : 1;
     52             for (int i = 0; i < 26; i ++)
     53                 h[nq].son[i] = h[q].son[i];
     54             h[nq].pre = h[q].pre;
     55             h[q].pre = h[np].pre = nq;
     56             for (; h[p].son[j] == q; p = h[p].pre)
     57                 h[p].son[j] = nq;
     58         }
     59     }
     60     last = np;
     61 }
     62 
     63 inline void BFS(int S)
     64 {
     65     int l = 0, r = 0;
     66     q[0] = S;
     67     while (l <= r)
     68     {
     69         int z = q[l ++];
     70         for (int i = Head[z]; i; i = E[i].next)
     71         {
     72             int d = E[i].node;
     73             q[++ r] = d;
     74         }
     75     }
     76     for (; r; r --)
     77     {
     78         if (h[q[r]].pre)
     79             Size[h[q[r]].pre] += Size[q[r]];
     80     }
     81 }
     82 
     83 inline void dfs(int z)
     84 {
     85     if (Vis[z]) return ;
     86     Vis[z] = 1;
     87     for (int i = 0; i < 26; i ++)
     88         if (h[z].son[i])
     89         {
     90             dfs(h[z].son[i]);
     91             Size[z] += Size[h[z].son[i]];
     92         }
     93 }
     94 
     95 inline void Solve(int p, int k)
     96 {
     97     LL sum = 0;
     98     for (int i = 0; i < 26; i ++)
     99        if (h[p].son[i])
    100             sum += Size[h[p].son[i]];
    101     if (Size[p] - sum >= k) return ;
    102     k -= Size[p] - sum, sum = 0;
    103     for (int i = 0; i < 26; i ++)
    104         if (h[p].son[i])
    105         {
    106             if (sum < k && k <= sum + Size[h[p].son[i]])
    107             {
    108                 putchar('a' + i);
    109                 Solve(h[p].son[i], k - sum);
    110                 break ;
    111             }
    112             else sum += Size[h[p].son[i]];
    113         }
    114 }
    115 
    116 int main()
    117 {
    118     #ifndef ONLINE_JUDGE
    119         freopen("3998.in", "r", stdin);
    120         freopen("3998.out", "w", stdout);
    121     #endif
    122     
    123     scanf("%s", s);
    124     scanf("%d%d", &t, &k);
    125     n = strlen(s);
    126     for (int i = 0; i < n; i ++)
    127         addchar(s[i]);
    128     if (t)
    129     {
    130         for (int i = 1; i <= tot; i ++)
    131             addedge(h[i].pre, i);
    132         BFS(0);
    133     }
    134     dfs(0);
    135     if (Size[0] < k) puts("-1");
    136         else Solve(0, k);
    137     putchar('
    ');
    138     
    139     #ifndef ONLINE_JUDGE
    140         fclose(stdin);
    141         fclose(stdout);
    142     #endif
    143     return 0;
    144 }
    3998_Gromah
  • 相关阅读:
    安卓开发之有序广播
    安卓开发之无序广播
    安卓开发之短信发送器的开发
    安卓开发之隐式意图与显示意图
    安卓root权限 被提示Read-only file system 或 Operation not permitted 解决方案
    gcc 的基本使用和静态库、动态库的制作与使用
    Python类的学习,看这一篇文章就够了!
    Qt 添加程序图标和系统托盘图标
    Qt ListWidget item 发起拖放
    Qt 接受拖放
  • 原文地址:https://www.cnblogs.com/gromah/p/4452558.html
Copyright © 2011-2022 走看看