您的位置:首页 > 其它

CodeForces 825F String Compression---这个KMP很DP

2017-08-04 15:09 453 查看
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 s1exactly 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.

Example

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 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, c2is 1, s2 is z, c3 is 4, s3 is ab.

题意:给一个字符串,求它的最小循环节的长度和最大循环数目位数之和。

思路:KMP自带求循环节的功能,如果不知道,看这里-->http://www.cnblogs.com/jackge/archive/2013/01/05/2846006.html

题目中字符长度不超过8000,可以直接暴力求解i位置开始长度为j的字符串的循环节,每次取得最小的循环节,用dp[i+j]定义从i位置开始长度为j的字符串(即:i+j位置结尾的字符串)的最小循环节长度与最大循环次数的位数之和这个子状态,

状态转移方程:dp[j+i] = min(dp[j+i], dp[i]+cnt[j/xlen]+xlen):dp[i]表是i位置结尾的字符串最小循环节长度与最大循环数目的最小和,cnt[j/xlen]表示最大循环次数的位数,xlen表示最小循环节长度;

特别注意当j%xlen!=0时,说明没有循环节可寻,此时最大循环位数自然为1,最小循环长度就是j.

# 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;//sprintf的返回值是字符的长度
for(int i=0; i<len; ++i)
{
kmp(s+i,len-i,pre);
// cout<<s+i<<endl;
for(int j=1; j+i<=len; ++j)
{
int xlen = j-pre[j];
//cout<<j<<"--"<<xlen<<endl;//i为起位置,j为从i开始的字符串长度,xlen表示该字符串循环节最小循环节长度。
// cout<<i+j<<endl;
if(j%xlen == 0)
dp[j+i] = min(dp[j+i], dp[i]+cnt[j/xlen]+xlen),cout;
else dp[j+i] = min(dp[j+i], dp[i]+1+j);
}
}
printf("%d\n",dp[len]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces dp string kmp