[CF825F] String Compression 题解

2024-04-11 21:20

本文主要是介绍[CF825F] String Compression 题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意

给定一个字符串 S S S,其中出现循环的子串压缩后长度为:循环节出现次数十进制下的位数+循环节长度,无循环的串也需要压缩。求压缩后的最小长度。

思路

对于串 T T T,对其执行 KMP 算法后得到 n x t nxt nxt 数组,可能的最小循环节长度 l e n len len 即为 ∣ T ∣ − n x t ∣ T ∣ |T|-nxt_{|T|} TnxtT,其中 ∣ T ∣ |T| T 表示 T T T 的长度;如果 l e n ∤ ∣ T ∣ len\nmid |T| lenT T T T 中无小的循环节(即循环节长度为 ∣ T ∣ |T| T)。对 S S S 串进行压缩可以认为是把 S S S 分成若干个子串,这些子串全部完全压缩。

考虑 dp。设 f i f_i fi 表示将 S S S 串的前 i i i 个字符进行压缩的最小长度。初始 f i = i + 1 f_i=i+1 fi=i+1。转移方程即为: f i ← min ⁡ { f j + c n t j + 1 , i } ( 1 ≤ j < i ≤ ∣ S ∣ ) f_i\gets\min\{f_j+cnt_{j+1,i}\}\ (1\le j<i\le |S|) fimin{fj+cntj+1,i} (1j<iS),其中 c n t x , y cnt_{x,y} cntx,y 表示将 S S S [ x , y ] [x,y] [x,y] 这个部分完全压缩后的长度,求法即为:对于每个 1 ≤ i ≤ ∣ S ∣ 1\le i\le |S| 1iS,都将 S S S 的前 i − 1 i-1 i1 个字符删除后跑 KMP,求得的 ( j − i + 1 ) − n x t j ( i ≤ j ≤ ∣ S ∣ ) (j-i+1)-nxt_j\ (i\le j\le |S|) (ji+1)nxtj (ijS) 即为 c n t i , j cnt_i,j cnti,j,注意判断是否能够整除。时间复杂度 O ( n 2 ) O(n^2) O(n2)

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 8005;
char S[maxn]; int f[maxn],nxt[maxn];
int count(int x) { // 数出循环节十进制位数int res = 0;while (x) res ++, x /= 10;return res;
}
int n;
void KMP(char S[]) { // 求出的 nxt 数组下标从起点开始int len = strlen(S + 1);memset(nxt,0,sizeof(nxt)); for (int i = 2,now = 0;i <= len;i ++) {while (now && S[i] != S[now + 1]) now = nxt[now];if (S[i] == S[now + 1]) now ++;nxt[i] = now;}
}
int main() {scanf("%s",S + 1); n = strlen(S + 1);for (int i = 1;i <= n;i ++)f[i] = i + 1;for (int i = 0;i <= n;i ++) {KMP(S + i); // 以每个 i 为开头跑出 nxt 数组for (int len = 1;i + len <= n;len ++) { // 枚举完全压缩的区间长度int j = i + len;if (len % (len - nxt[len]) == 0) // 存在循环节f[j] = min(f[j],f[i] + count(len / (len - nxt[len])) + len - nxt[len]);else f[j] = min(f[j],f[i] + len + 1); // 否则只能整个压缩}}printf("%d",f[n]);return 0;
}

这篇关于[CF825F] String Compression 题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/895215

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

hdu2072(string的应用)

单词数 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 25447    Accepted Submission(s): 5957 Problem Description lily的好朋友xiaoou333最近很空,他