题意:压缩字符串,把字符串分成若干个子串,每个子串可以被压缩成“循环次数 \(+\) 循环节”的形式,求最小长度。

dp 求 lcp

先 \(O(n^2)\) dp 求出所有后缀对的 \(lcp_{x,y}\),(也可以 \(\text{SA}\) \(O(\log n)\) 求,但是本题 \(n=8000\) 还有 \(\dfrac{1}{2}\) 的常数,没必要这么做。

然后我们设 \(dp_{i}\) 表示当前 \(i-1\) 前面的位置都已经压缩完成的最小长度。枚举最小循环节长度 \(j\),一直往后 \(dp\),直到 \(lcp_{i,r}\lt j\) 为止。

对其中所有的 \(i+kj\),将 \([i,i+kj-1]\) 压缩成一个子串进行转移,转移到 \(i+kj\)。提前预处理出每个循环次数和字符串长度的对应关系 \(O(1)\) 转移到 \(i+kj\),转移复杂度 \(O(n\log n)\),总的复杂度是 \(O(n^2\log n)\) 的,但是常数较小,可过。

双模哈希

首先,显而易见的贪心,如果当前确定了要把 \([l,r]\) 压缩成一个子串,则一定选择最小的循环节。因为选择更大的循环节,循环节的长度增加是循环次数长度减少的 \(10\) 倍。

然后,考虑如何计算 \([l,r]\) 中的最小循环节。

我们考虑计算 \(f_{l,r}\) 表示以 \([l,r]\) 为第一个循环节,最多往后循环次数。我们可以从后往前枚举左端点,然后只考虑 \(f_{r+1,r+(r-l+1)}\),因为这是我们从 \(f_{l,r}\) 往后拓展的必经之路。我们可以用字符串哈希 \(O(1)\) 判断两个区间是否相等,从而判断能否从后面进行转移,如果可以,\(f_{l,r}=f_{r+1,r+(r-l+1)}+1\),否则,\(f_{l,r}=1\)。

接下来有一个假做法,就是枚举 \(i\) 之后的最小循环节长度,然后贪心选取尽可能多的循环次数。但是这样会 WA,因为我们可能要留一点字符给后面的循环节。

我们考虑计算 \(g_{l,r}\) 表示 \([l,r]\) 的最小循环节。我们的思路是从小到大枚举,然后使用 \(f_{l,r}\) 往后延申直到超出 \(f_{l,r}\) 的次数。这样就是对每个 \([l,r]\) 都循环 \(f_{l,r}\) 次对 \(g_{l,l+k\times len}\) 进行贡献。复杂度是 \(O(n^2\log n)\),和前面的做法没什么区别。

但是我们如果使用一些线性筛的思想,使得每个 \(g_{l,r}\) 只被自己的最小循环节贡献,如果当前的循环节已经存在循环节,就不往更大的区间进行贡献。我们发现这是正确的。

首先,如果一个长度 \(n\) 的区间存在两种循环节,长度分别是 \(x\) 和 \(y\),那么一定存在 \(\gcd(x,y)\) 长度的循环节。我们假设 \(x<y\),考虑所有长度为 \(y\) 的循环节将所有长为 \(\gcd(x,y)\) 的单元分成 \(n/y\) 段,每段都有 \(y\) 个不同的,而划分出 \(y\) 个剩余类,例如 0 1 2 0 1 2 0 1 ... 。然后考虑 \(x\) 对 \(y\) 的覆盖,因为 \(x'=\dfrac{x}{\gcd(x,y)}\) 和 \(y'=\dfrac{y}{\gcd(x,y)}\) 是互质的,所以其唯一重合的地方是 \(n'=\dfrac{n}{\gcd(x,y)}\)。那么从 \(0\) 开始每次跳 \(x'\) 遍历可以遍历 \(y'\) 的整个剩余系。

或者说,对 \(y'\) 的剩余系而言,因为 \(x'\) 和 \(y'\) 互质,所以设 \(S\) 是模 \(y\) 的剩余系,则 \(xS=S\),即\(0,x',2x',3x',\cdots,(y'-1)x'\) 模 \(y'\) 两两不同余。则所有模 \(x'\) 意义下的等价类 \(0\) 都两两不同的对应了模 \(y\) 意义下的所有等价类恰好一次,得到所有 \(\gcd(x,y)\) 长的单元都是相同的,则存在长度 \(\gcd(x,y)\) 的循环节。

那么,任何的区间 \([l,r]\) 都存在唯一最小的循环节 \(s\),使得任意其他循环节 \(t\),都存在 \(k|s|=|t|\)。那么在 \(s\) 贡献到 \([l,r]\) 的同时,其其他循环节也都被贡献到了,由于先枚举小的区间,我们就不会调用 \([l,r]\) 的任意其他循环节覆盖别人,所以计算 \(g_{l,r}\) 的过程中,每个\([l,r]\) 只被扫到一次,总复杂度 \(O(n^2)\)。

最后,设 \(dp_i\) 表示 \(i-1\) 以前都成功配对,然后枚举当前压缩的大区间右端点 \(r\),使用其最小循环节进行贡献,预处理每个数字对应的长度,就可以做到 \(O(1)\) 计算单个转移,总的转移是 \(O(n)\) 的,这一环节的复杂度也是 \(O(n^2)\)。

从而,整个算法的复杂度是 \(O(n^2)\)。注意哈希和匹配的常数较大,可能成为算法瓶颈(大常数 \(O(n^2)\))

const ll P1=998244353,P2=1000000007,S1=114,S2=191;
ll h1[8005],h2[8005],pw1[8005],pw2[8005],ipw1[8005],ipw2[8005];
int cnt[8005][8005],bit[8005],dp[8005];
int f[8005][8005];
st s;int n;
inline pll hsh(int l,int r){
ll r1=(h1[r]-h1[l-1]*pw1[r-l+1]%P1+P1)%P1;
ll r2=(h2[r]-h2[l-1]*pw2[r-l+1]%P2+P2)%P2;
return pll(r1,r2);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>s;n=s.size();s='$'+s;
rp(i,n)h1[i]=(h1[i-1]*S1+s[i]-'a')%P1;
rp(i,n)h2[i]=(h2[i-1]*S2+s[i]-'a')%P2;
pw1[0]=pw2[0]=ipw1[0]=ipw2[0]=1;
rp(i,n)pw1[i]=pw1[i-1]*S1%P1;
rp(i,n)pw2[i]=pw2[i-1]*S2%P2;
rep(i,1,9)bit[i]=1;
rep(i,10,99)bit[i]=2;
rep(i,100,999)bit[i]=3;
rep(i,1000,8000)bit[i]=4;
per(l,1,n)rep(r,l,n){
int len=r-l+1;cnt[l][r]=1;
if(r+len<=n&&hsh(l,r)==hsh(r+1,r+len))cnt[l][r]=cnt[r+1][r+len]+1;
}
dp[1]=0;
rep(i,2,n+1)dp[i]=1e9;
rep(l,1,n)rep(r,l,n)if(f[l][r]==0){
int len=r-l+1;
for(int i=1;l+i*len-1<=n&&i<=cnt[l][r];i++){
f[l][l+i*len-1]=i;
}
}
rep(l,1,n)rep(r,l,n)
dp[r+1]=min(dp[r+1],dp[l]+bit[f[l][r]]+(r-l+1)/f[l][r]);
cout<<dp[n+1]<<endl;
return 0;
}
//Crayan_r

CF825F - String Compression的更多相关文章

  1. CF825F String Compression 解题报告

    CF825F String Compression 题意 给定一个串s,其中重复出现的子串可以压缩成 "数字+重复的子串" 的形式,数字算长度. 只重复一次的串也要压. 求压缩后的 ...

  2. UVA 1351 十三 String Compression

    String Compression Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit ...

  3. 【leetcode】443. String Compression

    problem 443. String Compression Input ["a","a","b","b"," ...

  4. 443. String Compression

    原题: 443. String Compression 解题: 看到题目就想到用map计数,然后将计数的位数计算处理,这里的解法并不满足题目的额外O(1)的要求,并且只是返回了结果array的长度,并 ...

  5. 213. String Compression【LintCode java】

    Description Implement a method to perform basic string compression using the counts of repeated char ...

  6. 213. String Compression【easy】

    Implement a method to perform basic string compression using the counts of repeated characters. For ...

  7. codeforces 825F F. String Compression dp+kmp找字符串的最小循环节

    /** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: d ...

  8. Codeforces 825F - String Compression

    825F - String Compression 题意 给出一个字符串,你要把它尽量压缩成一个短的字符串,比如一个字符串ababab你可以转化成3ab,长度为 3,比如bbbacacb转化成3b2a ...

  9. 区间DP UVA 1351 String Compression

    题目传送门 /* 题意:给一个字符串,连续相同的段落可以合并,gogogo->3(go),问最小表示的长度 区间DP:dp[i][j]表示[i,j]的区间最小表示长度,那么dp[i][j] = ...

  10. LeetCode_443. String Compression

    443. String Compression Easy Given an array of characters, compress it in-place. The length after co ...

随机推荐

  1. 静态文件配置 django连接MySQL django模型层初识 ORM基本语句

    目录 静态文件配置 1. 问题描述 2. 静态文件 3. 资源访问 form表单属性补充 action method 请求方法 get请求 post请求 views层 request对象 reques ...

  2. MySQL简介、下载、密码修改及基本使用

    目录 存取数据的演变史 数据库软件应用史 数据库的本质 数据库的分类 MySQL简介 MySQL基本使用 系统服务的制作 密码相关操作 SQL与NoSQL 数据库重要概念 基本SQL语句 存取数据的演 ...

  3. Surp Suite入门

    BurpSuite代理工具是以拦截代理的方式,拦截所有通过代理的网络流量,如客户端的请求数据.服务器端的返回信息等.Burp Suite主要拦截HTTP和HTTPS 协议的流量,通过拦截,Burp S ...

  4. python 之选择结构(if --elif --else)

    python中有三种结构:顺序结构.选择结构.循环结构,此处介绍选择结构. if -- else 结构: if 判断条件: 执行语句 else: 执行语句 当if后面的判断条件为真(True)时,执行 ...

  5. 未授权访问漏洞之Redis漏洞复现

    前言 未授权访问漏洞简写是SSRF(Server-Side Request Forgery:服务器端请求伪造),是一种服务器端提供了可以从其他服务器获取资源和数据的功能,但没有对目标地址进行过滤和限制 ...

  6. 什么是RPC? (全面了解)

    一:RPC 1.什么是RPC? RPC 是指远程过程调用,也就是说两台服务器,A 和 B,一个应用部署在A 服务器上,想要调用B 服务器上应用提供的函数或方法,由于不在一个内存空间,不能直接调用,需要 ...

  7. [python] 基于blind-watermark库添加图片盲水印

    blind-watermark是一个能够给图片添加/解析基于频域的数字盲水印的Python库.图像水印image watermark是指在图片里添加文本或图形,以标记图片的来源.但是图像水印会破坏原图 ...

  8. [生命科学] snapgene 构建载体方法分享

    snapgene 构建载体方法分享 文章目录 snapgene 构建载体方法分享 1. Snapgene 构建载体-酶切位点法 2. 载体构建--同源重组法 3. 总结 1. Snapgene 构建载 ...

  9. Spring MVC的运行流程

    Spring MVC的运行流程 摘要:本文档主要结合官方给出的Spring MVC流程图结合一个简单的Spring MVC实例,分析并介绍了Spring MVC的运行流程. 目录 Spring MVC ...

  10. win32com操作word API精讲&项目实战 预告

    对win32com的使用和研究有好一段时间了,想起本人刚开始做word编程项目时的各种痛苦:网上能找到的都是简单的示例,如同hello word一般,嚼之无味又无可奈何.读office的word接口文 ...