题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6583

大致题意是说可以花费p在字符串后添加一个任意字符,或者花费q在字符串后添加一个当前字符串的子串。问最少花费多少可以得到目标串。

一开始想到的dp,dp[i]为得到目标串的1-i的最小花费。

那么dp[i]=min{dp[i-1]+p,dp[j-1]+q},s[j~i]应该为s[1~j-1]的子串。

我们可以知道dp数组是一个单调递增的数组,用反证法可以证明:dp[i]由dp[i-1]转移就不用说了,如果dp[i]是由dp[j]转移过来且dp[i-1]>dp[i],那么dp[i-1]也可以由dp[j]转移过来,所以不合法。

因为dp数组是递增的,则dp[i]如果是由第二种方法转移过来,则j应该是最小的。所以求最小的j满足s[j~i]应该为s[1~j-1]的子串。

dp[i]的第二种转移位置,应该在是dp[i-1]的第二种转移位置j的基础上往后移。

所以用双指针的位置,一个代表i,一个代表j,每次在后缀自动机上添加第j个位置的字符,如果s[j~i]在后缀自动机上可以匹配,则转移,不然就把j往后移。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<string>
 7 #include<queue>
 8 using namespace std;
 9 typedef long long ll;
10 const ll maxn = 2e5 + 10;
11 const ll inf = 1e18;
12 struct SAM {
13     int cnt, last, now;
14     int len[maxn * 2], ch[maxn * 2][30], fa[maxn * 2];
15     void clear() {
16         for (int i = 0; i <= cnt; i++) {
17             len[i] = fa[i] = 0;
18             memset(ch[i], 0, sizeof(ch[i]));
19         }
20     }
21     void insert(int x) {
22         int np = ++cnt, p = last;
23         len[np] = len[p] + 1, last = np;
24         while (p && !ch[p][x])
25             ch[p][x] = np, p = fa[p];
26         if (!p)
27             fa[np] = 1;
28         else {
29             int q = ch[p][x];
30             if (len[q] == len[p] + 1)
31                 fa[np] = q;
32             else {
33                 int nq = ++cnt;
34                 len[nq] = len[p] + 1;
35                 memcpy(ch[nq], ch[q], sizeof(ch[nq]));
36                 fa[nq] = fa[q];
37                 fa[np] = fa[q] = nq;
38                 while (p&&ch[p][x] == q)
39                     ch[p][x] = nq, p = fa[p];
40             }
41         }
42     }
43     int Match(int x) {
44         return ch[now][x];
45     }
46     void withdraw(int lens) {
47         while (now&&len[fa[now]] >= lens)now = fa[now];
48         if (now == 0)now = 1;
49     }
50     void Tran(int x, int lens) {
51         now = ch[now][x];
52         if (now == 0)now = 1;
53         withdraw(lens);
54     }
55 }SA;
56 ll dp[maxn];
57 char s[maxn];
58 int main() {
59     while (~scanf("%s", s + 1)) {
60         ll p, q, len;
61         memset(dp, 0, sizeof(dp));
62         scanf("%lld%lld", &p, &q);
63         len = strlen(s + 1);
64         SA.cnt = SA.last = SA.now = 1;
65         SA.insert(s[1] - 'a');
66         dp[1] = p;
67         int l = 2, r = 1;
68         for (int i = 2; i <= len; i++) {
69             r++;
70             dp[i] = dp[i - 1] + p;
71             while ((!SA.Match(s[i] - 'a') || r - l + 1 > (i + 1) / 2) && l <= r) {
72                 SA.insert(s[l++] - 'a');
73                 SA.withdraw(r - l);
74             }
75             SA.Tran(s[i] - 'a', r - l + 1);
76             if (l <= r)
77                 dp[r] = min(dp[r], dp[l - 1] + q);
78         }
79         printf("%lld\n", dp[len]);
80         SA.clear();
81     }
82
83 }

View Code

转载于:https://www.cnblogs.com/sainsist/p/11307838.html

[2019杭电多校第一场][hdu6583]Typewriter(后缀自动机dp)相关推荐

  1. 2019年杭电多校第一场 1001题blank(DP)HDU6578

    2019年杭电多校第一场 1001题blank(DP)HDU6578 解决思路,开一个DP数组来存储0 1 2 3四个字符最后出现的位置,并且在DP中已经==排好序==. DP开四维,DP[i][j] ...

  2. 2019杭电多校第一场 Operation HDU - 6579

    题意:给出一个序列,两种操作,求区间[l,r]的区间最大异或和,和在末尾添加一个数 思路:强制在线,保存每个线性基的数值,接下去直接去搜第r个线性基,但要保持时间比l要大,新增了一个pos数组代表一个 ...

  3. 2019杭电多校第一场 HDU 6599

    题解 枚举所有的回文串 注意,本质不同的回文串最多只有∣S∣|S|∣S∣个 在这些回文串中,有一些是满足要求的,我们对这些串打上标记 首先跑一个ManacherManacherManacher,然后枚 ...

  4. 2022“杭电杯”中国大学生算法设计超级联赛 (1) 杭电多校第一场 2 3 4 5 8 12

    题目 1002 Dragon slayer 标程 1003 Backpack AC代码 1004 Ball AC代码 1008 Path AC代码 1009 Laser AC代码 1012 Alice ...

  5. 2019杭电多校第二场1009 HDU6599:求本质不同的回文串长度及数量

    hdu6599:求本质不同的回文串长度及数量 hdu6599题意: manacher+后缀自动机+倍增 $O(nlog(n))$ manacher+后缀数组+二分 $O(nlog(n))$ 回文树(回 ...

  6. HDU-6578 Blank(DP)2019暑假杭电多校第一场

    题意:一行有n个空格编号1~n; 每一个空格中填入0,1,2,3中的一个数字.且满足m个限制l,r,x:满足在区间[l,r]正好有x种不同的数字. 有多少种方法可以填充空格以满足所有条件? 思路:dp ...

  7. 杭电多校第一场第三题 Backpack(异或dp+bitset)

    问题描述 爱丽丝有一个容量背包m她现在想用一些物品填充! 爱丽丝有n项目,每个项目都有一个卷v我和值w我. 是否可以从n个项目中选择多个项目,以使背包完全装满(即体积的总和等于背包容量)?如果是这样, ...

  8. 2019杭电多校第九场 Rikka with Cake (hdu6681)

    题意:给出一个n * m的蛋糕,切 k 刀,每次从一个点(x,y)向 上下左右的一个方向切,问最后蛋糕被切成了几块 题解:显然,蛋糕的块数就是那么多线段的交点数 + 1.先离散,考虑向左切和向上切的, ...

  9. 2022 杭电多校 第一场

    文章目录 1011 Random 1012 Alice and Bob 1003 Backpack 1002 Dragon slayer 1009 Laser 1011 Random 签到 求一下期望 ...

  10. 2022杭电多校第一场

    A String 题意:求s串1-i(1 <i <n)子串的贡献,贡献为公共前后缀相交并且相交部分长度为k的倍数的数量 题解做法是用exkmp求出s串与所有后缀的LCP后,设LCP为x,那 ...

最新文章

  1. 近400万奖金!2021全国人工智能大赛来了
  2. python svm超参数_grid search 超参数寻优
  3. 人工智能能否跨越意识鸿沟?
  4. VBA 里面注册dll
  5. pyqt5 QMainWindow 居中
  6. mysql-5.7.17-winx64的安装配置
  7. apache压力测试
  8. Java中的内存泄露的几种可能
  9. mysql 修改数据库的数据库_如何更改MySQL数据库的数据库名
  10. Python实现局域网内屏幕广播的技术要点分析
  11. Redis-数据结构04-整数集合(intset)
  12. 自动化运维之ansible-安装部署与基础命令篇
  13. 43.连接 Internet
  14. php系统变量有哪些,php预定义系统变量
  15. MIUI系统刷第三方Recovery+Magisk
  16. C#学习笔记29——c#使用word、excel、pdf
  17. 街机中国 FBA4droid 应用
  18. 迷你迅雷,IE下载加速补丁(转)
  19. mysql入门篇1———单表操作
  20. 你知道 biangbiang 面和编码有什么关系吗?万字长文,手拉手带你一步步认识编码

热门文章

  1. [web]EL表达式失效
  2. R语言爱好者必备——R语言速查表(高清版可下载)
  3. 基于 Keras 用深度学习预测时间序列
  4. 21天实战人工智能系列:人工智能产品经理最佳实践(2)
  5. java判断枚举是否包含_java判断枚举是否包含
  6. MySQL的约束、事务、字符串、日期、数学相关及其他补充
  7. VI 编辑器保存命令
  8. 静态代码块与构造函数的作用
  9. python中字典dictionary详解及基本使用
  10. 12c emcc Algorithm negotiation fail