题目链接: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往后移。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
typedef long long ll;
const ll maxn = 2e5 + ;
const ll inf = 1e18;
struct SAM {
int cnt, last, now;
int len[maxn * ], ch[maxn * ][], fa[maxn * ];
void clear() {
for (int i = ; i <= cnt; i++) {
len[i] = fa[i] = ;
memset(ch[i], , sizeof(ch[i]));
}
}
void insert(int x) {
int np = ++cnt, p = last;
len[np] = len[p] + , last = np;
while (p && !ch[p][x])
ch[p][x] = np, p = fa[p];
if (!p)
fa[np] = ;
else {
int q = ch[p][x];
if (len[q] == len[p] + )
fa[np] = q;
else {
int nq = ++cnt;
len[nq] = len[p] + ;
memcpy(ch[nq], ch[q], sizeof(ch[nq]));
fa[nq] = fa[q];
fa[np] = fa[q] = nq;
while (p&&ch[p][x] == q)
ch[p][x] = nq, p = fa[p];
}
}
}
int Match(int x) {
return ch[now][x];
}
void withdraw(int lens) {
while (now&&len[fa[now]] >= lens)now = fa[now];
if (now == )now = ;
}
void Tran(int x, int lens) {
now = ch[now][x];
if (now == )now = ;
withdraw(lens);
}
}SA;
ll dp[maxn];
char s[maxn];
int main() {
while (~scanf("%s", s + )) {
ll p, q, len;
memset(dp, , sizeof(dp));
scanf("%lld%lld", &p, &q);
len = strlen(s + );
SA.cnt = SA.last = SA.now = ;
SA.insert(s[] - 'a');
dp[] = p;
int l = , r = ;
for (int i = ; i <= len; i++) {
r++;
dp[i] = dp[i - ] + p;
while ((!SA.Match(s[i] - 'a') || r - l + > (i + ) / ) && l <= r) {
SA.insert(s[l++] - 'a');
SA.withdraw(r - l);
}
SA.Tran(s[i] - 'a', r - l + );
if (l <= r)
dp[r] = min(dp[r], dp[l - ] + q);
}
printf("%lld\n", dp[len]);
SA.clear();
} }

[2019杭电多校第一场][hdu6583]Typewriter(后缀自动机&&dp)的更多相关文章

  1. 2019杭电多校第一场hdu6581 Vacation

    Vacation 题目传送门 update(O(n)) 看了那个O(n)的方法,感觉自己想的那个O(nlogn)的好傻,awsl. 0车最终通过停车线的时候,状态一定是某个车堵住后面的所有车(这个车也 ...

  2. [2019杭电多校第一场][hdu6582]Path(最短路&&最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 题意:删掉边使得1到n的最短路改变,删掉边的代价为该边的边权.求最小代价. 比赛时一片浆糊,赛后 ...

  3. [2019杭电多校第一场][hdu6579]Operation(线性基)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题目大意是两个操作,1个是求[l,r]区间子序列的最大异或和,另一个是在最后面添加一个数. 如果 ...

  4. [2019杭电多校第一场][hdu6578]Blank(dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578 计数问题想到dp不过分吧... dp[i][j][k][w]为第1-i位置中4个数最后一次出现的 ...

  5. 2019杭电多校第一场hdu6579 Operation(线性基)

    Operation 题目传送门 解题思路 把右边的数尽量往高位放,构造线性基的时候同时记录其在原序列中的位置,在可以插入的时候如果那个位置上存在的数字的位置比新放入的要小,就把旧的往后挤.用这种发现构 ...

  6. 2018 Multi-University Training Contest 1 杭电多校第一场

    抱着可能杭电的多校1比牛客的多校1更恐怖的想法 看到三道签到题 幸福的都快哭出来了好吗 1001  Maximum Multiple(hdoj 6298) 链接:http://acm.hdu.edu. ...

  7. 2019年杭电多校第一场 1009题String(HDU6586+模拟+单调栈)

    题目链接 传送门 题意 给你一个字符串,要你构造一个长为\(k\)的子串使得每个字母出现的次数在\([L_i,R_i](0\leq i\leq26)\)间且字典序最小. 思路 做这种题目就是要保持思路 ...

  8. 2019年杭电多校第一场 1004题Vacation(HDU6581+数学)

    题目链接 传送门 题意 有\(n+1\)辆车要过红绿灯,告诉你车的长度.与红绿灯的起点(题目假设红绿灯始终为绿).车的最大速度,问你第\(0\)辆车(距离最远)车头到达红绿灯起点的时间是多少(每辆车最 ...

  9. 2019年杭电多校第一场 1002题Operation(HDU6579+线性基)

    题目链接 传送门 题意 初始时有\(n\)个数,现在有\(q\)次操作: 查询\([l,r]\)内选择一些数使得异或和最大: 在末尾加入一个数. 题目强制在线. 思路 对于\(i\)我们记录\([1, ...

随机推荐

  1. java打印树形目录结构

    import java.io.File; public class MainTest { public static void main(String[] args) { String dirname ...

  2. CentOS6.5 安装gitlab以及gitolite迁移gitlab

    CentOS6.5 安装gitlab以及gitolite迁移gitlab gitlab 的安装使用以及数据结构 安装 环境: CentOS6.5 基于 nignx + unicorn 搭建的应用环境, ...

  3. MySQL 5.7

    博客地址:https://www.cnblogs.com/runningStudy/p/6444047.html mysql官网下载地址:https://downloads.mysql.com/arc ...

  4. man wc

    WC(1)        User Commands/用户命令            WC(1) NAME/名称       wc - print the number of newlines, wo ...

  5. 【微信小程序】使用vscode编写微信小程序项目

    1. 在微信开发者工具(以下简称:开发者)中新建一个模板微信小程序 2. 在开发者中将模拟器分隔开 3. 设置在保存时编译 4. 在vscode中打开项目目录 5. 下载代码提示插件 这样就可以在vs ...

  6. Spring源码构建

    1.下载spring源码并解压 https://codeload.github.com/spring-projects/spring-framework/zip/v5.0.2.RELEASE 打开bu ...

  7. .Net手动实现ORM及代码生自动成器

    序言 代码生成器 同时提供便捷的开发管理功能和多项开发工作中常用到的辅助工具功能,您可以很方便轻松地进行项目开发,让软件开发变得轻松而快乐!帮您快速开发项目,缩短开发周期,减少开发成本,大大提高了企业 ...

  8. Java——容器(Map)

    [Map接口]  

  9. VS2019界面透明、主题修改和导出设置

    目录 安装插件Color Theme Editor for Visual Studio 2019和ClaudiIDE 导入主题 背景修改 效果预览 导出设置遇到错误924 其他帮助文档 我自己用的主题 ...

  10. Maven的settings.xml配置详解

    子节点详细介绍转载:http://www.cnblogs.com/jingmoxukong/p/6050172.html?utm_source=gold_browser_extension 全局配置 ...