——本题来自杭电多校第一场

题意:给定一个字符串,主角需要用打字机将字符串打出来,每次可以:

1.花费p来打出任意一个字符

2.花费q来将已经打出的某一段(子串)复制到后面去

对于这种最优化的问题,我们可以考虑dp

设置dp[i]表示已经打出前i个字符的最小花费,这样设状态是没有后效性的。

那么显然有:

            dp[i] = dp[i-1] + p

这样就可以将第一种方案的转移算出来了

对于第二种方案,我们可以考虑维护一个j,使得 s[j+1……i] 是 s[1……j] 的子集(1),也就是说 s[j+1……i] 可以由 s[1……j] 中的一部分复制而来

具体实现利用后缀自动机来维护 s[1……j] 这个字符串,当不满足上述条件(1)时,就不断往后添加字符,并让 j = j + 1

当满足上述条件(1)时,就可以有:

            dp[i] = min(dp[i], dp[j] + q) 

具体细节:当找到满足条件的j时,记录在后缀自动机上最后的匹配位置,每次i或者j变化的时候,检查cur的link指针指向位置的终点集合长度是否大于等于已匹配长度,如果是,就可以往link指针方向跳(对于这一部分不理解的话建议复习SAM的终点集合的性质),之后继续匹配。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=;
const int kind=;
struct state
{
state *Next[kind],*link;
int len;
state()
{
link=;
len=;
memset(Next,,sizeof(Next));
}
};
int sz;
state st[maxn*+];
inline state* newnode(int len = )
{
memset(st[sz].Next,,sizeof(st[sz].Next));
st[sz].link=;
st[sz].len=len;
return &st[sz++];
}
state *root,*last;
void extend(int w)
{
state* p=last;
state* cur=newnode(p->len+);
while(p&&p->Next[w]==)
{
p->Next[w]=cur;
p=p->link;
}
if(p)
{
state* q=p->Next[w];
if(p->len+==q->len)
cur->link=q;
else
{
state* clone=newnode(p->len+);
memcpy(clone->Next,q->Next,sizeof(q->Next));
clone->link=q->link;
q->link=clone;
cur->link=clone;
while(p&&p->Next[w]==q)
{
p->Next[w]=clone;
p=p->link;
}
}
}
else cur->link=root;
last=cur;
} #define ll long long
char s[maxn];
ll dp[maxn];
int main()
{
while(~scanf("%s",s+))
{
sz=;
root=newnode();
last=root;
ll p,q;
scanf("%lld%lld",&p,&q);
int n=strlen(s+);
int j=;
dp[]=p;
extend(s[]-'a');
state* cur=root->Next[s[]-'a'];
for(int i=;i<=n;i++)
{
dp[i]=dp[i-]+p;
while()
{
while(cur!=root && cur->link->len>=i-j-) cur=cur->link;
if(cur->Next[s[i]-'a']!=NULL)
{
cur=cur->Next[s[i]-'a'];
break;
}
else
extend(s[++j]-'a');
}
//cout<<i<<' '<<j<<endl;
dp[i]=min(dp[i],dp[j]+q);
}
printf("%lld\n",dp[n]);
}
}

注:由于本代码的sam用的是指针,HDU中G++编译器的指针为8字节,所以交G++的时候可能会因为常数太大而T,但是交C++可以600ms左右A掉

HDU 6583 Typewriter 题解的更多相关文章

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

    Typewrite \[ Time Limit: 1500 ms\quad Memory Limit: 262144 kB \] 题意 给出一个字符串 \(s\),现在你需要构造出这个字符串,你每次可 ...

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

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

  3. 致初学者(一): HDU 2000~ 2013题解

    对于开始学习C语言程序设计或C++程序设计面向过程部分的同学来说,利用在线OJ网站进行实践训练,对提高自己的编程能力很有好处.国内外OJ网站很多,每个都去看看,去刷个题,是不现实的,也没必要.即使一个 ...

  4. 爆零后的感受外加一道强联通分量HDU 4635的题解

    今天又爆零了,又是又,怎么又是又,爆零爆多了,又也就经常挂嘴边了,看到这句话,你一定很想说一句””,弱菜被骂傻,也很正常啦. 如果你不开心,可以考虑往下看. 翻到E(HDU 4635 Strongly ...

  5. 致初学者(二): HDU 2014~ 2032题解

    下面继续给出HDU 2014~2032的AC程序,供大家参考.2014~2032这19道题就被归结为“C语言程序设计练习(三) ”~“C语言程序设计练习(五) ”. HDU 2014:青年歌手大奖赛_ ...

  6. 致初学者(三): HDU 2033~ 2043题解

    下面继续给出HDU 2033~2043的AC程序,供大家参考.2033~2043这10道题就被归结为“ACM程序设计期末考试(2006/06/07) ”和“2005实验班短学期考试 ”. HDU 20 ...

  7. HDU 5961 传递 题解

    题目 我们称一个有向图G是 传递的,当且仅当对任意三个不同的顶点a,,若G中有 一条边从a到b且有一条边从b到c ,则G中同样有一条边从a到c. 我们称图G是一个 竞赛图,当且仅当它是一个有向图且它的 ...

  8. HDU 5963 朋友 题解

    题目 B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的: 给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根.接下来从女生开始,双 ...

  9. HDU 1106 排序 题解

    排序 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...

随机推荐

  1. 【洛谷p1190】接水问题

    接水问题[题目链接] 咱也不知道为啥咱就是想写博客emmm 尽管这个题是2010年的普及组但是我太菜了并不会写emm 其实感觉这道题是纯纯正正的大模拟: 算法标签中的贪心是没有意义的啊?? SOLUT ...

  2. Reactjs 列表优化的一些心得

    前言 在应用开发中,列表是我们使用频率非常高的一种展现形式,在reactjs项目中更是如此.无处不在的使用更是需要我们小心触发性能瓶颈的深水炸弹. 下面就我最近的总结出的几点心得分享给大家,有什么问题 ...

  3. 通过设置代理解决AndroidStudio无法下载gradle问题

    一.AndroidStudio代理 我们平时在使用android studio时,难免需要从android官网下载一些项目运行所需要的SDK文件,但是因为android官网在国外,访问起来会比较慢,所 ...

  4. js中基本数据类型与引用数据类型的本质区别

    代码 /** * 基本数据类型:string, number, boolean, null, undefined. * * 说明: * 基本数据类型的变量是保存在栈内存中的,基本数据类型的值 * 直接 ...

  5. 2019-3-9-通过-frp-开启服务器打开本地的-ZeroNet-服务器外网访问

    title author date CreateTime categories 通过 frp 开启服务器打开本地的 ZeroNet 服务器外网访问 lindexi 2019-03-09 11:47:4 ...

  6. ABBYY FineReader 14.0.107.232 Enterprise 下载和安装使用

    目录 1. 按 2. 软件功能 3. 软件特色 4. 安装说明 5. 激活说明 6. 下载地址 1. 按 ABBYY FineReader 是款功能强大的OCR文字识别软件:它支持者用户进行使用文档的 ...

  7. 常用Linux Shell命令组合

    序号 任务 命令组合 1 删除0字节文件 find . -type f -size 0 -exec rm -rf {} \;find . type f -size 0 -delete 2 查看进程,按 ...

  8. python时间测量

    使用自定义装饰器测量时间 def test_time(func): def inner(*args, **kw): t1 = datetime.datetime.now() print('开始时间:' ...

  9. Windows Linux双系统 删除 Linux 系统

    首先修复引导,之前是先安装Windows后安装Linux,所以引导是Linux的 先需要修复其引导为Windows, 先下载MbrFix,网上说64位需要下载4位,实测都可以. 下载好以后,就在C盘用 ...

  10. python struct中的pack unpack

    python struct中的pack unpack pytyon tuple元组 print struct.unpack("!ihb", buffer)  结果为7 //pyth ...