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
Output
Input
Output
Input
Output
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;
}
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 176B] Word Cut (脑洞+KMP+dp)
- CodeForces 825F Educational Round #25 F:KMP最小循环节+DP
- Codeforces 432D Prefixes and Suffixes(KMP+dp)
- Codeforces 432D Prefixes and Suffixes(KMP+dp)
- Codeforces 432D Prefixes and Suffixes(KMP+dp)
- Codeforces 10D LCIS 求最长公共上升子序列及输出这个子序列 dp
- Obsessive String - CodeForces 494 B KMP+dp
- Codeforces 10D LCIS 找出最长公共子和产量增加这个序列 dp
- codeforces 432D Prefixes and Suffixes (kmp+dp)
- Password CodeForces - 126B [KMP+DP思维]
- codeforces 126B B. Password(kmp+dp)
- Codeforces 808G Anthem of Berland[dp][kmp]
- codeforces 908E(概率dp)
- codeforces 478D D. Red-Green Towers(dp)
- CodeForces 571B Minimization(dp)
- CodeForces 603A_Alternative Thinking (DP)
- codeforces 788C The Great Mixing( BFS / dp+bitset优化 )
- Codeforces-834D The Bakery 线段树优化DP
- DP 之 codeforces 416B
- codeforces 583B B. Once Again...(dp)