Typewrite

\[Time Limit: 1500 ms\quad Memory Limit: 262144 kB
\]

题意

给出一个字符串 \(s\),现在你需要构造出这个字符串,你每次可以花费 \(q\) 在末尾加上任意一个字符或者花费 \(p\) 复制任意一段已经构造出来的子串到末尾,问最少需要花费多少。

思路

令 \(dp[i]\) 表示构造到第 \(i\) 位最少花费多少。

第一种情况,直接花费 \(q\) 添加在末尾,\(dp[r] = dp[r-1]+q\)

第二种情况,花费 \(p\) 复制一部分到末尾,设 \(s[l+1...r]\) 是被复制的串,那么此时需要满足 \(s[l+1...r] \in s[1...l]\),则 \(dp[r] = dp[l] + p\),此时的问题就是如何维护 \(l\)。

利用后缀自动机可以表示出所有子串的性质,\(pos\) 表示满足条件的 \(s[l+1...r]\) 所在后缀自动机上的节点位置。

每次插入 \(s[r]\) 时,就是从 \(s[l+1...r-1]\in s[1...l] \implies s[l+1...r] \in s[1...l]\) 的过程,所以要让 \(pos\) 节点往 \(s[r]\) 方向移动。如果能移动的话,直接将 \(pos\) 移动过去,否则就扩展这个自动机,将 \(s[l]\) 插入后在尝试能否移动。在这个过程中,不断维护 \(pos\) 在满足条件范围的节点上。

  1. 一个问题就是 \(pos\) 何时不能向 \(s[r]\) 方向移动,这种情况就是 \(pos\) 节点不存在 \(s[r]\) 这条边。
  2. 令一个问题就是如何维护 \(pos\) 在符合条件的范围内,我们知道 \(pos\) 节点包含了同样性质的长度从 \(len[fa[pos]]+1\) 到 \(len[pos]\) 内的子串,我们只要保证这里面最短的子串 \(len[fa[pos]]+1\) 不要太长,需要可以表示出后面那部分的串。在插入 \(s[r]\) 之前,此时只到 \(r-1\),需要保证 \(len[fa[pos]]+1 \leq (r-1)-(l+1)+1\),插入 \(s[r]\) 后,此时到了 \(r\),需要保证 \(len[fa[pos]]+1 \leq r-(l+1)+1\)
  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <ctime>
  5. #include <cmath>
  6. #include <stack>
  7. #include <queue>
  8. #include <cfloat>
  9. #include <string>
  10. #include <vector>
  11. #include <cstdio>
  12. #include <bitset>
  13. #include <cstdlib>
  14. #include <cstring>
  15. #include <iostream>
  16. #include <algorithm>
  17. #define lowbit(x) x & (-x)
  18. #define mes(a, b) memset(a, b, sizeof a)
  19. #define fi first
  20. #define se second
  21. #define pii pair<int, int>
  22. #define INOPEN freopen("in.txt", "r", stdin)
  23. #define OUTOPEN freopen("out.txt", "w", stdout)
  24. typedef unsigned long long int ull;
  25. typedef long long int ll;
  26. const int maxn = 2e5 + 10;
  27. const int maxm = 1e5 + 10;
  28. const ll mod = 1e9 + 7;
  29. const ll INF = 1e18 + 100;
  30. const int inf = 0x3f3f3f3f;
  31. const double pi = acos(-1.0);
  32. const double eps = 1e-8;
  33. using namespace std;
  34. int n, m;
  35. int cas, tol, T;
  36. struct Sam {
  37. int node[maxn<<1][27], fa[maxn<<1], step[maxn<<1];
  38. int sz, last;
  39. int newnode() {
  40. mes(node[++sz], 0);
  41. fa[sz] = step[sz] = 0;
  42. return sz;
  43. }
  44. void init() {
  45. sz = 0;
  46. last = newnode();
  47. }
  48. void insert(int k) {
  49. int p = last, np = last = newnode();
  50. step[np] = step[p]+1;
  51. for(; p&&!node[p][k]; p=fa[p])
  52. node[p][k] = np;
  53. if(p == 0) {
  54. fa[np] = 1;
  55. } else {
  56. int q = node[p][k];
  57. if(step[q] == step[p]+1) {
  58. fa[np] = q;
  59. } else {
  60. int nq = newnode();
  61. for(int i=1; i<=26; i++)
  62. node[nq][i] = node[q][i];
  63. fa[nq] = fa[q];
  64. step[nq] = step[p]+1;
  65. fa[np] = fa[q] = nq;
  66. for(; p&&node[p][k]==q; p=fa[p])
  67. node[p][k] = nq;
  68. }
  69. }
  70. }
  71. } sam;
  72. char s[maxn];
  73. ll dp[maxn];
  74. int main() {
  75. while(~scanf("%s", s+1)) {
  76. sam.init();
  77. int len = strlen(s+1);
  78. ll p, q;
  79. scanf("%lld%lld", &q, &p);
  80. ll ans = 0;
  81. int l=0, pos=0;
  82. dp[0] = 0;
  83. for(int r=1; r<=len; r++) {
  84. dp[r] = dp[r-1]+q;
  85. int k = s[r]-'a'+1;
  86. while(!sam.node[pos][k]) {
  87. sam.insert(s[++l]-'a'+1);
  88. while(pos && sam.step[sam.fa[pos]]>r-l-2)
  89. pos = sam.fa[pos];
  90. if(!pos) pos = 1;
  91. }
  92. pos = sam.node[pos][k];
  93. while(pos && sam.step[sam.fa[pos]]>r-l-1)
  94. pos = sam.fa[pos];
  95. if(!pos) pos = 1;
  96. dp[r] = min(dp[r], dp[l]+p);
  97. }
  98. printf("%lld\n", dp[len]);
  99. }
  100. return 0;
  101. }

HDU 6583 Typewriter(后缀自动机)的更多相关文章

  1. HDU - 6583 Typewriter (后缀自动机+dp)

    题目链接 题意:你要打印一段字符串,往尾部添加一个字符需要花费p元,复制一段字符到尾部需要花费q元,求打印完全部字符的最小花费. 一开始想的贪心,后来发现忘了考虑p<q的情况了,还纳闷怎么不对. ...

  2. HDU 6583 Typewriter 题解

    ——本题来自杭电多校第一场 题意:给定一个字符串,主角需要用打字机将字符串打出来,每次可以: 1.花费p来打出任意一个字符 2.花费q来将已经打出的某一段(子串)复制到后面去 对于这种最优化的问题,我 ...

  3. HDU 4622 Reincarnation 后缀自动机

    模板来源:http://blog.csdn.net/zkfzkfzkfzkfzkfzkfzk/article/details/9669747 解法参考:http://blog.csdn.net/dyx ...

  4. HDU 4622 Reincarnation 后缀自动机 // BKDRHash(最优hash)

    Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) P ...

  5. str2int HDU - 4436 (后缀自动机)

    str2int \[ Time Limit: 3000 ms\quad Memory Limit: 131072 kB \] 题意 给出 \(n\) 个串,求出这 \(n\) 个串所有子串代表的数字的 ...

  6. Reincarnation HDU - 4622 (后缀自动机)

    Reincarnation \[ Time Limit: 3000 ms\quad Memory Limit: 65536 kB \] 题意 给出一个字符串 \(S\),然后给出 \(m\) 次查询, ...

  7. Good Article Good sentence HDU - 4416 (后缀自动机)

    Good Article Good sentence \[ Time Limit: 3000 ms\quad Memory Limit: 32768 kB \] 题意 给出一个 \(S\) 串,在给出 ...

  8. HDU 4641 K-string 后缀自动机 并查集

    http://acm.hdu.edu.cn/showproblem.php?pid=4641 https://blog.csdn.net/asdfgh0308/article/details/4096 ...

  9. Hdu 4622 Reincarnation(后缀自动机)

    /* 字符串长度较小, 可以离线或者直接与处理所有区间的答案 动态加入点的时候, 因为对于其他点的parent构造要么没有影响, 要么就是在两个节点之间塞入一个点, 对于minmax的贡献没有改变 所 ...

随机推荐

  1. Elastic Stack 7.5.0白金版永不过期

    适用版本:7.4.0~7.5.0 警告:本文章仅限于学习,非商业用途. 目录结构 # 先创建相关目录,具体结构如下: /opt |-- bulid # 编译目录 | |- src |-- instal ...

  2. windows上 nginx 配置代理服务,配置多域名,以及最简单实现跨域配置

    Nginx,不用多说啦,大家都熟悉的不能再熟悉了,它是一款轻量级的高性能Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,最近在本地研究将nginx和resin配合使用,使服务 ...

  3. Prometheus监控学习笔记之容器监控Grafana模块

    0x00 概述 Grafana 是一个开源的,可以用于大规模指标数据的可视化项目,甚至还能对指标进行报警.基于友好的 Apache License 2.0 开源协议,目前是prometheus监控展示 ...

  4. NETCore使用带有权限验证的Swagger

    原文:NETCore使用带有权限验证的Swagger 文章目录 Swagger 什么是Swagger NuGet安装 Startup注册Swagger 设置默认首页打开Swagger 为接口添加注释 ...

  5. ajax 执行成功以后返回的数据走的是error方法而不是success方法的问题

    今天在一个功能的时候发现写的ajax的方法执行后台代码成功后返回前台时执行的是error方法而不是success方法,代码如下 jQuery('#form').ajaxSubmit({ type: & ...

  6. Ubuntu 18.04 RTX2080(ti) + tensorflow-gpu + cuda9.0 + gcc5 兼容性问题解决

    0.下载display driver.cuda和cudnn RTX2080 Display Driver cuda cudnn 1. 禁止系统默认的显卡驱动 打开系统黑名单 sudo gedit /e ...

  7. UIPath RPA 自动化脚本 机器人从入门到精通

    本文链接:https://blog.csdn.net/qq_27256783/article/details/93619818 一.UiPath介绍 UiPath 是RPA(Robotic Proce ...

  8. JDK 监控和故障处理工具

    JDK 监控和故障处理工具 JDK 命令行工具 这些命令在 JDK 安装目录下的 bin 目录下: jps (JVM Process Status): 类似 UNIX 的 ps 命令.用户查看所有 J ...

  9. Computer Networking: A Top Down Approach

    目录 Chapter 1: Computer Networks and the Internet 1. What is the Internet? 2. The Network Edge 3. The ...

  10. 【转载】C#如何往DataTable中新增一个数据列

    在C#中的Datatable数据变量的操作过程中,有时候我们需要往现有的DataTable中新增一个自定义数据列,该列在原有的DataTable变量中并不存在,属于用户手工自定义新增的数据列,在往Da ...