[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][ ...
随机推荐
- Java编程思想:一个小小的控制框架
这个实验我很喜欢,学到了非常多的东西: import java.util.ArrayList; import java.util.List; public class Test { public st ...
- MLlib特征变换方法
Spark1.6.2.2.3 PCA 算法介绍: 主成分分析是一种统计学方法,它使用正交转换从一系列可能相关的变量中提取线性无关变量集,提取出的变量集中的元素称为主成分.使用PCA方法可以对变量集合进 ...
- 【题解】生日蛋糕-C++
Description 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体.设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, ...
- 简单的量子算法(一):Hadamard 变换、Parity Problem
Hadamard Transform Hadamard 变换在量子逻辑门中提过,只不过那时是单量子的Hadamard门,负责把\(|1\rangle\)变成\(|-\rangle\),\(|0\ran ...
- Java-面向对象oop
在提到面向对象的时候,大多数的书上面介绍的是简短的 类是对象的集合,对象是类的实例化.这样笼统的说法的确可以概括面向对象的思想,但却不能让一个刚入门的人理解到面向对象. 在这里先介绍一下类,当你在Ja ...
- 百度OCR 文字识别 Android安全校验
百度OCR接口使用总结: 之前总结一下关于百度OCR文字识别接口的使用步骤(Android版本 不带包名配置 安全性弱).这边博客主要介绍,百度OCR文字识别接口,官方推荐使用方式,授权文件(安全模式 ...
- c++ 动态规划(数塔)
c++ 动态规划(dp) 题目描述 观察下面的数塔.写一个程序查找从最高点到底部任意位置结束的路径,使路径经过数字的和最大. 每一步可以从当前点走到左下角的点,也可以到达右下角的点. 输入 5 13 ...
- PHP与ECMAScript_4_常用数学相关函数
PHP ECMAScript 向上取整 ceil($number) Math.ceil( number ) 向下取整 floor($number) Math.floor( number ) 绝对值 a ...
- jQuery写toTop(回到顶部)效果
在通常的网站开发中,页面有时候会很长,尤其是一些电商网站,为了提高用户的体验效果,我们通常会增加一个回到顶部的按钮,这个按钮我们同城会使用fixed定位,将其定位在当前可视区域某一固定位置.这个效果用 ...
- js的位运算(其它语言也通用)
左移运算符(<<) 该运算符有2个运算数,a<<b,将a左移相当于a乘以2的b次方,2个运算符要求是整数,或可以转换成整数的. 如:1<<2 =4 "1& ...