P4302-[SCOI2003]字符串折叠【区间dp】
正題
題目鏈接:https://www.luogu.com.cn/problem/P4302
題目大意
一個(gè)字符串,對(duì)于一個(gè)字符串AAA。可以將連續(xù)的nnn個(gè)AAA縮成n(A)n(A)n(A)。求最短的長(zhǎng)度能夠表述出給定字符串
解題思路
定義fi,jf_{i,j}fi,j?表示表示出i~ji\sim ji~j的字符串的最短方法。那么不考慮折疊的話有正常區(qū)間dpdpdp轉(zhuǎn)移即fi,j=min{fi,k+fk+1,j}(i≤k<j)f_{i,j}=min\{f_{i,k}+f_{k+1,j}\}(i\leq k<j)fi,j?=min{fi,k?+fk+1,j?}(i≤k<j)
然后對(duì)于一段區(qū)間[l,r][l,r][l,r]考慮折疊,我們枚舉長(zhǎng)度lenlenlen的約數(shù)kkk,判斷能否用長(zhǎng)度為kkk的字符串折疊。有轉(zhuǎn)移fi,j=min{fi,i+k?1+2+zlen/k}(k?>[i,j])f_{i,j}=min\{f_{i,i+k-1}+2+z_{len/k}\}(k->[i,j])fi,j?=min{fi,i+k?1?+2+zlen/k?}(k?>[i,j])(ziz_izi?表示iii的位數(shù))
時(shí)間復(fù)雜度O(n3n)O(n^3\sqrt n)O(n3n?)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,z[110],f[110][110]; char s[110]; bool check(int l,int r,int len){if((r-l+1)%len!=0)return 0;for(int i=l+len;i<=r;i++)if(s[i-len]!=s[i])return 0;return 1; } int main() {scanf("%s",s+1);n=strlen(s+1);memset(f,0x3f,sizeof(f));for(int i=1;i<=n;i++)z[i]=z[i/10]+1,f[i][i]=1;for(int l=2;l<=n;l++){for(int i=1;i+l-1<=n;i++){int j=i+l-1;for(int k=i;k<j;k++)f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);for(int k=1;k<l;k++)if(check(i,j,k))f[i][j]=min(f[i][j],f[i][i+k-1]+2+z[l/k]);}}printf("%d",f[1][n]); }總結(jié)
以上是生活随笔為你收集整理的P4302-[SCOI2003]字符串折叠【区间dp】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 塔娜花日个人资料简历 塔娜花日简介
- 下一篇: YbtOJ#20064-[NOIP202