题目链接: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. git概述(三)

    Bug分支: 当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交: 并不是你不想提交,而是工作只进行 ...

  2. Arduino-LiquidCrystal_I2C 液晶库

    I2C转接板上[PCF8574T转接板]VCC接5V,GND接GND,SCL接SCL(即A05),SDA接SDA(即A04) 常用的函数是 lcd.init(),lcd初始化 setCursor(x, ...

  3. 【NOIP2015模拟10.22】最小代价

    前言 本来在比赛上就想到最小生成树了,但不相信这道题那么简单,然后就没有然后了... 题目 给出一幅由n个点m条边构成的无向带权图. 其中有些点是黑点,其他点是白点. 现在每个白点都要与他距离最近的黑 ...

  4. 软件安装——JRE多版本问题

    [Q]运行UMongo.exe文件时显示错误信息“The registry refers to a nonexsistent JAVA Runtime Envioroment or the Runti ...

  5. Ubuntu 16.04下使用docker部署rabbitmq

    (以下docker相关的命令,需要在root用户环境下或通过sudo提升权限来进行操作.) 1.拉取rabbimq镜像到本地 docker pull rabbitmq 2. Docker运行rabbi ...

  6. SourceTree跳过初始设置

    转载https://www.cnblogs.com/xiofee/p/sourcetree_pass_initialization_setup.html 如何跳过初始设置,只需要在安装路径中添加一个a ...

  7. progress组件(进度条)

    progress组件:进度条 progress组件的属性: percent:类型:number 设置百分比 (0~100) show-info:类型:布尔 在进度条右侧显示百分比 border-rad ...

  8. qbzt day4 下午

    有向图的强连通分量 强联通:两个点之间可以互相到达 如果某个图任意两个点都是强联通的,那么称这个图强联通 如果一个图的子图是强联通的,那么称这个图是强联通子图 一个图的极大强联通子图被称作强连通分量 ...

  9. nginx代理前端项目

    参考:https://segmentfault.com/a/1190000013980557  https://segmentfault.com/a/1190000013267839 注意 1.只能有 ...

  10. 【转】python---方法解析顺序MRO(Method Resolution Order)<以及解决类中super方法>

    [转]python---方法解析顺序MRO(Method Resolution Order)<以及解决类中super方法> MRO了解: 对于支持继承的编程语言来说,其方法(属性)可能定义 ...