HDU5470 Typewriter (SAM+单调队列优化DP)
Typewriter
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 720 Accepted Submission(s): 225
1) Assume you have typewritten a string s, then you can add a character after s, and the cost of adding each character is given to you.
2) Assume you have typewritten a string s, you can select a substring of s and copy it, then you can paste it after s once. The cost to select a character is A,and the cost to copy and paste a string are all equal B.
Now, you should help senior to typewrite the article by using the minimum cost, can you help her?
For each test case:
The first line includes a string s (1≤|s|≤10^5) composed by lowercase letters, indicating the article senior want to typewrite.
The second line includes 26 integers, indicating the cost to add character ‘a’, ‘b’, ‘c’…, and so on.
The third line includes two integers A and B.
All the integers in the input are in the range of [1,10^9]. It is guaranteed that the total length of s doesn't exceed 1.2×106.
Please output “Case #k: answer”(without quotes) one line, where k means the case number count from 1, and the answer is the minimum cost to typewrite the article.
题意:
给你一串字符以及单独打印每一个字母的代价,对于一个字母,你可以选择直接打印,也可以选择利用复制粘贴的方法来完成。对于复制粘贴,每次选择长度为i的字符串的代价是i*A,复制的代价是B,粘贴的代价也是B。即复制并粘贴一个长度为x的字符串的代价是x*A+2*B。现在问把这一整个字符串打印出来的代价是多少。
思路:
考虑DP, dp[i]:表示前i个字符打印完成的最小代价,则我们可以得到dp[i]=min(dp[i-1]+val[s[i]] , dp[j]+ (i-j)*A+2*b);那么这样的DP的时间复杂度是O(n^2),对于1e6的数据来说是无法接受的。
我们定义j为最小的一个位置,可以使得1..j的子串包含j+1..i的子串。经过观察,我们可以发现,这个j一定是单调的。也就是说,随着i的变大,j一定只增不减,这个很好理解。如果对于上一个长度来说最小的位置是j,对于当前决策,增加了一个长度,j肯定是要么增加要么不变。所以我们就可以利用这个单调性,用单调队列来优化这个dp.
如何保证在复杂度时间内判断某个串中是否包含另外一个串。也即,字符串s中,一个子串是否包含另外一个子串。如此,还是可能需要用到s的所有的子串,所以说还是用后缀自动机。每次,我们维护j,j的移动取决于前面部分的子串是否包含后面的子串。具体来说,对于当前的j,j+1~i-1在自动机上匹配到的位置x,如果对于新的i,自动机上面如果仍然有后继,那么j不动。如果没有,那么我就要考虑移动j了,移动的过程中,把新的s[j+1]添加到自动机中,继续匹配,如果添加到一定位置,发现x有s[i]这个后继了,那么停止;或者说,当j+1~i-1的长度缩短到x的parent指针所指节点的长度的时候,x则发生跳转,直接跳到其最长的后缀那里去。因为在移动的过程中,需要匹配的串也逐渐变短,短到一定程度就会变成原本串的一个最长后缀。就这样已知移动然后匹配,找到j移动到i或者发现点x有s[i]这个后继。
如此,对于当前i确定了j之后,我们就可以修改单调队列中的值,把所有小于j的决策都去掉,然后再选取目前最优的决策更新。最后把当前的状态结果也当作决策加入单调队列中。一边dp一边维护单调队列和j,同时还不断的把字符添加到SAM中。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pli pair<ll,int>
#define mkp make_pair
const int INF=0x3f3f3f3f;
const int maxn=1e5+;
int T;
char s[maxn];
int fa[maxn<<],l[maxn<<],nxt[maxn<<][];
int last,tot;
ll val[],dp[maxn],A,B;
pli q[maxn];
void Init()
{
last=tot=;
l[tot]=fa[tot]=;
memset(nxt[tot],,sizeof nxt[tot]);
} int NewNode()
{
++tot; fa[tot]=l[tot]=;
memset(nxt[tot],,sizeof nxt[tot]);
return tot;
} void Insert(int ch)
{
int np=NewNode(),p=last;
last=np; l[np]=l[p]+;
while(p&&!nxt[p][ch]) nxt[p][ch]=np,p=fa[p];
if(!p) fa[np]=;
else
{
int q=nxt[p][ch];
if(l[q]==l[p]+) fa[np]=q;
else
{
int nq=NewNode();
l[nq]=l[p]+;
memcpy(nxt[nq],nxt[q],sizeof nxt[q]);
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
while(p&&nxt[p][ch]==q) nxt[p][ch]=nq,p=fa[p];
}
}
} int main()
{
scanf("%d",&T);
for(int cas=;cas<=T;++cas)
{
Init();
scanf("%s",s+);
int n=strlen(s+);
for(int i=;i<;++i) scanf("%lld",&val[i]);
scanf("%lld%lld",&A,&B);
int pos=;dp[]=;
int L=,R=,nt=,j=,len=,pa;
for(int i=;i<=n;++i)
{
int ch=s[i]-'a';
dp[i]=dp[i-]+val[ch];
pa=fa[pos]; nt=nxt[pos][ch];
while(!nt&&j+<i)
{
if(pos!=&&--len==l[pa]) pos=pa,pa=fa[pos];
++j; Insert(s[j]-'a');
nt=nxt[pos][ch];
}
if(!nt)
{
pos=;L=R=; ++j;
Insert(s[j]-'a');
}
else pos=nt,++len;
while(L<R && q[L].second<j) ++L;
if(L!=R) dp[i]=min(dp[i],q[L].first+1ll*i*A+2ll*B);
q[R++]=mkp(dp[i]-i*A,i);
while(L<R-&&q[R-].first<=q[R-].first) --R,q[R-]=q[R];
}
printf("Case #%d: %lld\n",cas,dp[n]);
} return ;
}
HDU5470 Typewriter (SAM+单调队列优化DP)的更多相关文章
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- bzoj1855: [Scoi2010]股票交易--单调队列优化DP
单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【单调队列优化dp】 分组
[单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...
- [小明打联盟][斜率/单调队列 优化dp][背包]
链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
随机推荐
- 连接xshell 时 连不上的问题
最近这一周由于自己的xshell突然连接不到虚拟机,在网上找了很多种方法也没能解决,以至于自己在学习很多知识的时候都没能很好的去验证,去尝试.最后在求助大佬的时候终于将xshell重新连接到了虚拟 ...
- Comparable接口的实现和使用
1.什么是Comparable接口 此接口强行对实现它的每个类的对象进行整体排序.此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 .实现此接口的对象列表(和数组)可 ...
- SpringBoot Web篇(二)
摘要 继上一篇 SpringBoot Web篇(一) 文件上传 当我们服务器需要接收用户上传的文件时,就需要使用MultipartFile作为参数接收文件.如下: @PostMapping(" ...
- package.json文件内容介绍
概述 每个项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称.版本.许可证等元数据).npm install命令根据这个配置文件, ...
- Android状态栏兼容4.4.4与5.0,Android5.0状态栏由半透明设置为全透明
//判断android 版本然后设置Systembar颜色 public void initSystemBar() { Window window = getWindow(); //4.4版本及以上 ...
- 都是为了生活组——‘’都是为了吃饭”微信小程序评价
基于NABCD评论作品,及改进建议 1.根据NABCD评论,作品的选题 N(Need,需求) 纠结症是目前在年轻人身上普遍存在着的问题,食堂食物众多,每次在吃饭前都要纠结好久,大大浪费了时间,还容易产 ...
- LMS自适应天线阵列设计 MATLAB
在自适应天线课上刚刚学了LMS自适应阵,先出一个抢先版贴一下结果,抢先某个小朋友一步. 关于LMS的具体介绍,直接看wiki里的吧,解释的比书上简明:传送门:https://en.wikipedia. ...
- mysql通俗易懂的数据库连接池原理及模拟实现
什么是数据库连接池? 当系统使用JDBC技术访问数据库时会创建一个connection对象,而该对象的创建过程是非常消耗资源的,并且创建对象的时间也特别长,假设系统一天有1万次的访问量,那么一天就会有 ...
- Java关于Resource leak: 's' is never closed的问题
Resource leak: 's' is never closed的问题 问题:在编写Java时出现了Resource leak: 's' is never closed的问题,也就是对象s下面的波 ...
- 揭秘String类型背后的故事——带你领略汇编语言魅力
字符串或串(String)是由数字.字母.下划线组成的一串字符.一般记为 s=“a1a2···an”(n>=0).它是编程语言中表示文本的数据类型.在程序设计中,字符串(string)为符号或数 ...