NC20238. [SCOI2003]字符串折叠
描述
折叠的定义如下:
如果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
C++(g++ 7.5.0) 解法, 执行用时: 4ms, 内存消耗: 492K, 提交时间: 2022-07-31 15:00:26
#include <bits/stdc++.h> using namespace std; int s1[104], f[104][104]; char s[105]; int check(int l, int r, int len){ for(int i = l; i <= r; i++){ if(i + len <= r && s[i] != s[i + len]) return 0; } return 1; } int main(){ int i, j, n, m, k, t, l; for(i = 2; i <= 9; i++) s1[i] = 1; for(i = 10; i <= 99; i++) s1[i] = 2; s1[100] = 3; scanf("%s", s); n = strlen(s); memset(f, 1, sizeof(f)); for(i = 0; i < n; i++) f[i][i] = 1; for(i = n - 1; i >= 0; i--){ for(j = i + 1; j < n; j++){ l = j - i + 1; for(k = i; k < j; k++) f[i][j] = min(f[i][j], f[i][k] + f[k+1][j]); for(k = i; k < j; k++){ t = k - i + 1; if(l % t != 0) continue; if(check(i, j, t)) f[i][j] = min(f[i][j], s1[l / t] + 2 + f[i][k]); } } } printf("%d", f[0][n-1]); return 0; }
C++14(g++5.4) 解法, 执行用时: 4ms, 内存消耗: 896K, 提交时间: 2019-08-20 16:16:47
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int dp[10005][10005],n;char a[110000]; bool check(int i,int k,int j) { if((j-k)%(k-i+1)) return false; int p=i; for(int t=k+1;t<=j;++t) { if(a[t]!=a[p]) return false; if(++p>k) p=i; } return true; } int calc(int x) { int b=0; for(;x;x/=10) ++b; return b; } int main() { scanf("%s",a+1); n=strlen(a+1); for(int i=1;i<=n;++i) for(int j=i;j<=n;++j) dp[i][j]=j-i+1; for(int i=n;i>=1;--i) for(int j=i+1;j<=n;++j) for(int k=i;k<j;++k) { dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); if(check(i,k,j)) dp[i][j]=min(dp[i][j],dp[i][k]+2+calc((j-k)/(k-i+1)+1)); } cout<<dp[1][n]<<endl; }
C++ 解法, 执行用时: 4ms, 内存消耗: 820K, 提交时间: 2021-08-16 14:35:34
#include<bits/stdc++.h> using namespace std; int dp[10005][10005],o; char a[1000000]; bool check(int i,int k,int j) { if((j-k)%(k-i+1)) return false; int p=i; for(int t=k+1; t<=j; ++t) { if(a[t]!=a[p]) return false; if(++p>k) p=i; } return true; } int calc(int x) { int b=0; for(;x; x/=10) ++b; return b; } int main() { scanf("%s",a+1); o=strlen(a+1); for(int i=1; i<=o; ++i) for(int j=i; j<=o; ++j) dp[i][j]=j-i+1; for(int i=o; i>=1; --i) for(int j=i+1; j<=o; ++j) for(int k=i; k<j; ++k) { dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); if(check(i,k,j)) dp[i][j]=min(dp[i][j],dp[i][k]+2+calc((j-k)/(k-i+1)+1)); } cout<<dp[1][o]<<endl; }