1. 程式人生 > 實用技巧 >字串摺疊(區間dp)

字串摺疊(區間dp)

題目連結:https://ac.nowcoder.com/acm/problem/20238

題目描述

摺疊的定義如下:

一個字串可以看成它自身的摺疊。記作S = S X(S)是X(X>1)個S連線在一起的串的摺疊。記作X(S) = SSSS…S(X個S)。
如果A = A’, B = B’,則AB = A’B’ 例如,因為3(A) = AAA, 2(B) = BB,所以3(A)C2(B) =
AAACBB,而2(3(A)C)2(B) = AAACAAACBB

給一個字串,求它的最短折疊。例如AAAAAAAAAABABABCCD的最短折疊為:9(A)3(AB)CCD。

輸入描述:

僅一行,即字串S,長度保證不超過100。

輸出描述:

僅一行,即最短的摺疊長度。

示例1
輸入
複製

NEERCYESYESYESNEERCYESYESYES

輸出
複製

14

思路:
#include<bits/stdc++.h>
#include<cstdio>
#define ll long long
using namespace std;
const int MMAX=2e2+5;
char s[MMAX];
int dp[MMAX][MMAX];
bool check(int l1,int r1,int l2,int r2) ///[l1,r1]是主串
{
    ///遍歷判斷是否是主串的子串
    int
rri=r2-l2+1; for(int i=l1;i<=r1;i++) { int lle=(i-l1)%rri; if(s[i]!=s[l2+lle]) return false; } return true; } int dfs(int l,int r) { int len=r-l+1; for(int le=1;le<=len;le++) { if(len%le==0) { if(check(l,r,l,l+le-1
)) return le; ///尋找最小子串 } } } int main() { scanf("%s",s+1); int len=strlen(s+1); memset(dp,0,sizeof(dp)); for(int i=1;i<=len;i++) dp[i][i]=1; for(int le=2;le<=len;le++) ///列舉長度 { for(int l=1;l<=len-le+1;l++) ///列舉起點 { int r=l+le-1; ///確定終點 dp[l][r]=r-l+1; ///確定初始值 for(int k=l;k<r;k++) ///列舉斷點 { int len1=k-l+1,len2=r-k; if(len1%len2==0) ///len1>len2 { if(check(l,k,k+1,r)) ///判斷len2是否是len1的子串 { int su1=dfs(k+1,r); int su2=(len1+len2)/su1; int su3=(len1+len2)/min(len1,len2); ///最小子串合併 if(su2>=100) dp[l][r]=min(dp[l][r],su1+5); else if(su2>=10) dp[l][r]=min(dp[l][r],su1+4); else dp[l][r]=min(dp[l][r],su1+3); ///整個字串整體合併 if(su3>=100) dp[l][r]=min(dp[l][r],dp[k+1][r]+5); else if(su3>=10) dp[l][r]=min(dp[l][r],dp[k+1][r]+4); else dp[l][r]=min(dp[l][r],dp[k+1][r]+3); } else dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]); } else if(len2%len1==0) ///len2>len1 { if(check(k+1,r,l,k)) ///判斷len1是否是len2的子串 { int su1=dfs(l,k); int su2=(len1+len2)/su1; int su3=(len1+len2)/len1; ///最小子串合併 if(su2>=100) dp[l][r]=min(dp[l][r],su1+5); else if(su2>=10) dp[l][r]=min(dp[l][r],su1+4); else dp[l][r]=min(dp[l][r],su1+3); ///整個字串整體合併 if(su3>=100) dp[l][r]=min(dp[l][r],dp[l][k]+5); else if(su3>=10) dp[l][r]=min(dp[l][r],dp[l][k]+4); else dp[l][r]=min(dp[l][r],dp[l][k]+3); } else dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]); } else dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]); } } } printf("%d\n",dp[1][len]); return 0; }