[SCOI2007]压缩(动态规划,区间dp,字符串哈希)
[SCOI2007]压缩
状态:设\(dp[i][j]\)表示前i个字符,最后一个\(M\)放置在\(j\)位置之后的最短字串长度.
转移有三类,用刷表法来实现.
第一种是直接往压缩串后面填字符,这样就是:
\]
另外一种就是往字串里添加\(R\),要满足相邻两个字符串是匹配的,可以用字符串哈希来快速匹,另外下面的\(k\)和\(sz\)要倍增往后跳(因为重复的串长在成倍增加,题目的样例解释的很清楚了).
\]
当然还要往后填\(M\)
\]
时间复杂度\(O(n^2logn)\)
代码很好懂.
#include<bits/stdc++.h>
#define ull unsigned long long
#define maxn 55
using namespace std;
const int base=233;
ull ha[maxn],pw[maxn];
char s[maxn];
int n,ans,dp[maxn][maxn];
ull gethash(int l,int r){return ha[r]-ha[l-1]*pw[r-l+1];}
int main()
{
scanf("%s",s+1);n=strlen(s+1);pw[0]=1;
for(int i=1;i<=n;i++)ha[i]=ha[i-1]*base+s[i];
for(int i=1;i<=n;i++)pw[i]=pw[i-1]*base;
memset(dp,0x3f,sizeof(dp));dp[1][0]=1;
//dp[i][j]表示前i个字符,上一个M放在j位置之后的最短加密字串
for(int i=1;i<=n;i++)
{
for(int j=0;j<i;j++)dp[i][i]=min(dp[i][i],dp[i][j]+1);
for(int j=0;j<=i;j++)
{
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1);//往后直接添加字母
if(i==j)continue;
int sz=i-j;ull haha=gethash(j+1,i);
for(int k=i+sz;k<=n;k+=sz)//倍增加R
{
if(haha==gethash(k-sz+1,k))//哈希匹配字符串
dp[k][j]=min(dp[k][j],dp[k-sz][j]+1);
else break;
haha=haha*pw[sz]+haha;sz<<=1;
}
}
}
ans=1e9;
for(int j=0;j<n;j++)ans=min(ans,dp[n][j]);
cout<<ans<<endl;
return 0;
}
[SCOI2007]压缩(动态规划,区间dp,字符串哈希)的更多相关文章
- [SCOI2007]压缩(区间dp)
神仙题,看了半天题解才看明白... 因为题目里说如果没有m,会自动默认m在最前面. 我们设计状态为dp[l][r][0/1]为在区间l到r中有没有m的最小长度. 转移:枚举我们要压缩的起点,dp[l] ...
- bzoj 1068: [SCOI2007]压缩【区间dp】
神区间dp 设f[l][r][0]为在l到r中压缩的第一个字符为M,并且区间内只有这一个M,f[l][r][0]为在l到r中压缩的第一个字符为M,并且区间内有两个及以上的M 然后显然的转移是f[i][ ...
- 1068. [SCOI2007]压缩【区间DP】
Description 给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息.压缩后的字符串除了小 写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上 ...
- BZOJ1068 [SCOI2007]压缩 【区间dp】
题目 给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息.压缩后的字符串除了小 写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位 ...
- 2018.10.20 bzoj1068: [SCOI2007]压缩(区间dp)
传送门 这题转移很妙啊. f[l][r][1/0]f[l][r][1/0]f[l][r][1/0]表示对于区间[l,r][l,r][l,r]有/无重复的机会时压缩的最小值. 那么可以从三种情况转移过来 ...
- 动态规划——区间dp
在利用动态规划解决的一些实际问题当中,一类是基于区间上进行的,总的来说,这种区间dp是属于线性dp的一种.但是我们为了更好的分类,这里仍将其单独拿出进行分析讨论. 让我们结合一个题目开始对区间dp的探 ...
- 动态规划——区间DP,计数类DP,数位统计DP
本博客部分内容参考:<算法竞赛进阶指南> 一.区间DP 划重点: 以前所学过的线性DP一般从初始状态开始,沿着阶段的扩张向某个方向递推,直至计算出目标状态. 区间DP也属于线性DP的一种, ...
- 模板 - 动态规划 - 区间dp
因为昨天在Codeforces上设计的区间dp错了(错过了上紫的机会),觉得很难受.看看学长好像也有学,就不用看别的神犇的了. 区间dp处理环的时候可以把序列延长一倍. 下面是 $O(n^3)$ 的朴 ...
- 动态规划---区间dp
今天写内网题,连着写了两道区间dp,这里就总结一下. 区间dp思想主要是先枚举f[i][j]中的i,再枚举j,再枚举一个1~j之间的变量k,一般是f[i][j] = max(f[i][j],f[i][ ...
随机推荐
- MyBatis 一对多映射
From<MyBatis从入门到精通> <!-- 6.1.2.1 collection集合的嵌套结果映射 和association类似,集合的嵌套结果映射就是指通过一次SQL查询将所 ...
- select模块(I/O多路复用)
0709自我总结 select模块 一.介绍 Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持 ...
- 从7点到9点写的小程序(用了模块导入,python终端颜色显示,用了点局部和全局可变和不可变作用域,模块全是自定义)
未完待续的小程序 要是能做的好看为啥不做的好看 在同目录下生成程序 1.程序文件 run.py from login import login from register import registe ...
- TinycoreLinux的安装使用
下载 http://www.tinycorelinux.net/7.x/x86_64/release/ distribution_files/ 05-Apr-2016 07:29 - src/ 24- ...
- Android学习总结之开发工具AndroidStudio的安装与配置
安装AndroidStudio 首先下载AndroidStudio的安装包,直接在百度AndroidStudio下载即可,安装过程简单,只需要修改安装路径(不要有空格和中文即可).然后下一步下一步就可 ...
- c语言进阶7-结构体
一. 结构体: 在程序设计基础当中我们学习了变量,变量可以节省使用空间相对于常量而言,大家来看下表: 学号 姓名 职位 性别 数学 英语 语文 总成绩 1 刘琳 班委 女 50 61 56 167 ...
- php重复开启session
虽然不知道 自己怎么就在一个后台系统页面中重复开启了session, 但是为了避免重复开始session的问题,可以使用: if (!session_id()) session_start(); 以上 ...
- 并发,并行,线程,进程,GIL锁
1.并发和并行 并发: 同时做某些事,但是强调同一时段做多件事 如:同一路口,发生了车辆要同时通过路面的时间. 并行: 互不干扰的在同一时刻做多件事 如:同一时刻,同时有多辆车在多条车道上跑,即同时发 ...
- Code blocks返回错误代码:Process returned -1073741819 (0xC0000005)
循环语句访问链表时,返回了错误代码: 逐项排查后,发现是由while循环引起的: 附上出错代码: do{ L=L->post; printf("%05d %d %05d\n" ...
- 改MySQL的编码方式,解决jdbc MySQL中文乱码问题
进MySQL安装目录,打开my.ini 这两个地方改成gbk 重启服务