1. 程式人生 > >Educational Codeforces Round 25 F. String Compression(kmp+dp)

Educational Codeforces Round 25 F. String Compression(kmp+dp)

targe 次數 技術分享 sprint define turn aps 有一種 枚舉

題目鏈接:Educational Codeforces Round 25 F. String Compression

題意:

給你一個字符串,讓你壓縮,問壓縮後最小的長度是多少。

壓縮的形式為x(...)x(...) x表示(...)這個出現的次數。

題解:

考慮dp[i]表示前i個字符壓縮後的最小長度。

轉移方程解釋看代碼,這裏要用到kmp來找最小的循環節。

當然還有一種找循環節的方式就是預處理lcp,然後通過枚舉循環節的方式。

這裏我用的kmp找的循環節。復雜度嚴格n2

技術分享
 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3
using namespace std; 4 5 void kmp_pre(char *x,int m,int *nxt){ 6 int i,j; 7 j=nxt[0]=-1,i=0; 8 while(i<m){ 9 while(-1!=j&&x[i]!=x[j])j=nxt[j]; 10 nxt[++i]=++j; 11 } 12 } 13 const int N=10000; 14 int len,nxt[N],dp[N],cnt[N]; 15 char s[N],buf[20],str[N]; 16 17
int main(){ 18 scanf("%s",s); 19 len=strlen(s); 20 F(i,1,len)cnt[i]=sprintf(buf,"%d",i),dp[i]=i+1; 21 F(i,0,len-1) 22 { 23 strcpy(str,s+i); 24 kmp_pre(str,len-i,nxt); 25 for(int j=1;i+j<=len;j++)//枚舉長度 26 { 27 int L=j-nxt[j];//以j結尾的子串的最小循環節
28 if(j%L==0)//如果這個子串的長度恰好能整除最小循環節,那麽可以按照最小循環節壓縮。 29 { 30 dp[i+j]=min(dp[i+j],dp[i]+L+cnt[j/L]); 31 }else dp[i+j]=min(dp[i+j],dp[i]+j+cnt[1]); 32 } 33 } 34 printf("%d\n",dp[len]); 35 return 0; 36 }
View Code

Educational Codeforces Round 25 F. String Compression(kmp+dp)