2024-07-16 21:09阅读: 9评论: 0推荐: 0

CF825F String Compression题解

思路

容易想到是个动态规划。首先设 fi 表示字符串前 i 个字符所组成的字符串的答案。状态定义好了,接下来就是考虑如何转移了。因为由 fi 可以得到所有 fj,其中 i+jlen,转移方程为 fi=fj+x,其中 x 为 字符串 i+1j 的最优压缩。

接下来只要把如何求最优压缩解决了这道题就做出来了。考虑暴力求解,随便选择一个前缀 T 遍历整个字符串,看 T 是否是原字符串的循环串。如何优化呢?我们要做的事情就是找一个最长前缀 T,使得字符串 T 是原字符串的循环串。有没有感觉似曾相识?对了,就是对字符串求一遍 KMPborder 数组。

所以转移方程就出来了 fi+k=min(fi+k,fi+(knxtk)+sum)

这道题也就做出来了,具体参见代码。

代码

#include <bits/stdc++.h>
using namespace std;
int f[100010];
int nxt[8010];
char s[8010], t[8010];
void kmp(char t[])
{
memset(nxt, 0, sizeof(nxt));
int j = 0;
nxt[1] = 0, nxt[0] = 0;
int len = strlen(t + 1);
for (int i = 2; i <= len; i++)
{
while (j && t[i] != t[j + 1])
j = nxt[j];
if (t[i] == t[j + 1])
j++;
nxt[i] = j;
}
}
int main()
{
cin >> s + 1;
int len = strlen(s + 1);
for (int i = 1; i <= len; i++)
f[i] = i + 1;
for (int i = 0; i < len; i++)
{
memset(t, 0, sizeof(t));
int ss = 0;
for (int j = i + 1; j <= len; j++)
{
t[++ss] = s[j];
}
kmp(t);
for (int k = 1; k + i <= len; k++)
{
if (k % (k - nxt[k]) == 0)
{
int cnt = k / (k - nxt[k]), sum = 0;
while (cnt)
sum++, cnt /= 10;
f[i + k] = min(f[i + k], f[i] + (k - nxt[k]) + sum);
}
else
f[i + k] = min(f[i + k], f[i] + 1 + k);
}
}
cout << f[len];
return 0;
}

本文作者:merlinkkk

本文链接:https://www.cnblogs.com/merlinkkk/p/18306124

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   merlinkkk  阅读(9)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开