Educational Codeforces Round 25 F. String Compression KMP找循环节+简单

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lifelikes/article/details/82945837

F. String Compression
time limit per test2 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard 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
inputCopy
aaaaaaaaaa
outputCopy
3
inputCopy
abcab
outputCopy
6
inputCopy
cczabababab
outputCopy
7
Note
In the first example Ivan will choose this compressed version: c1 is 10, s1 is a.

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

In the third example Ivan will choose this compressed version: c1 is 2, s1 is c, c2 is 1, s2 is z, c3 is 4, s3 is ab.

题意
给出一种压缩方式
假设压缩完后 字符串是 A1B1 A2B2 则有A1个B1串后面接着A2个B2串
给出一个字符串 ,问你压缩完后,最短长度是多少。
题解:
问题转换一下就是找一下最短循环节,字符串长度只有8000 允许O(n^2) 的算法
kmp可以在线性时间内找出循环节长度。
然后就是一个简单的DP了
dp[i] 表示 前i个字符压缩后最短长度是多少。

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int getlen(int n){
    int ans =0;
    while(n){
        ans++;
        n/=10;
    }
    return ans;
}
void getnext(int next[],int len,char S[]){
    //printf("%s\n",S);
    next[0]=0;
    for(int i=1;i<len;i++){
        int j = next[i-1];
        while(j && S[i]!=S[j]) j= next[j-1];
        next[i]=S[i]==S[j]? j+1:0;
    }
}
int getcir(int p,int next[]){
    return (p+1)%(p-next[p]+1)==0? p-next[p]+1:p+1;
}
const int MAX = 10000;
char str[MAX];
int num[MAX];
int dp[MAX];
int net[MAX];
int main(){
    //freopen("in.txt","r",stdin);
    scanf("%s",str+1);
    int len = strlen(str+1);
    for(int i=0;i<=len;i++){
        num[i]=getlen(i);
        //cout<<i<<":"<<num[i]<<endl;
    }
    memset(dp,0x3f,sizeof dp);
    dp[0]=0;
    getnext(net,len,str+1);
    for(int i=0;i<=len;i++){
        getnext(net,len-i,str+i+1);
        for(int j=i+1;j<=len;j++){
            int dis = j-i;
            int cirlen=getcir(j-i-1,net);
            //cout<<i<<","<<j<<","<<cirlen<<endl;
            dp[j]=min(dp[j],dp[i]+num[dis/cirlen]+cirlen);
        }
    }
    cout<<dp[len]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lifelikes/article/details/82945837