CF825F:String Compression(dp & kmp)

本文探讨了字符串压缩算法中的一种特殊形式,即通过重复模式的识别来最小化字符串表示长度的方法。通过对KMP算法的应用及十进制数长度的有效计算,实现了字符串压缩的最优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

F. String Compression
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Ivan wants to write a letter to his friend. The letter is a string s consisting of lowercase Latin letters.

Unfortunately, when Ivan started writing the letter, he realised that it is very long and writing the whole letter may take extremely long time. So he wants to write the compressed version of string s instead of the string itself.

The compressed version of string s is a sequence of strings c1, s1, c2, s2, ..., ck, sk, where ci is the decimal representation of number ai(without any leading zeroes) and si is some string consisting of lowercase Latin letters. If Ivan writes string s1 exactly a1 times, then string s2 exactly a2 times, and so on, the result will be string s.

The length of a compressed version is |c1| + |s1| + |c2| + |s2|... |ck| + |sk|. Among all compressed versions Ivan wants to choose a version such that its length is minimum possible. Help Ivan to determine minimum possible length.

Input

The only line of input contains one string s consisting of lowercase Latin letters (1 ≤ |s| ≤ 8000).

Output

Output one integer number — the minimum possible length of a compressed version of s.

Examples
input
aaaaaaaaaa
output
3
input
abcab
output
6
input
cczabababab
output
7
Note

In the first example Ivan will choose this compressed version: c1 is 10s1 is a.

In the second example Ivan will choose this compressed version: c1 is 1s1 is abcab.

In the third example Ivan will choose this compressed version: c1 is 2s1 is cc2 is 1s2 is zc3 is 4s3 is ab.

题意:给一个字符串,化成c1, s1, c2, s2, ..., ck, s的形式,表示C(十进制数字)个S并在一起,这部分对答案的贡献为C的长度加上S的长度,问表示整个字符串所需的最少值。

思路:直接的想法是dp[i]处理到第i为需要的最少值,那么怎么处理子串和它的循环节呢,参考别人做法的后知道KMP的next数组就带有这个功能,同时处理十进制数字的长度能用sprintf方便地打表。

# include <bits/stdc++.h>
using namespace std;
const int maxn = 8800;
char s[maxn], buf[20];
int cnt[maxn], dp[maxn]={0}, pre[maxn];
void kmp(char *s, int len, int pre[])
{
    pre[0] = pre[1] = 0;
    for(int i=1; i<len; ++i)
    {
        int j = pre[i];
        while(j && s[i]!=s[j]) j=pre[j];
        pre[i+1] = s[j]==s[i]?j+1:0;
    }
}
int main()
{
    scanf("%s",s);
    int len = strlen(s);
    for(int i=1; i<=len; ++i)
        cnt[i] = sprintf(buf, "%d", i), dp[i] = i+1;
    for(int i=0; i<len; ++i)
    {
        kmp(s+i,len-i,pre);
        for(int j=1; j+i<=len; ++j)
        {
            int xlen = j-pre[j];//循环节长度。
            if(j%xlen == 0)
                dp[j+i] = min(dp[j+i], dp[i]+cnt[j/xlen]+xlen);
            else dp[j+i] = min(dp[j+i], dp[i]+1+j);
        }
    }
    printf("%d\n",dp[len]);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值