问题
问题就是折叠字符串,例如ACBACB可以折叠成2(ACB),并且折叠可以嵌套,字符串长度是n(1<n<=100),求最短的折叠
分析
状态比较易懂,dp[i][j]代表[i,j]这一段能压缩成的最短字符串
然后分为三种情况决策,1.不能压缩的 2.能部分压缩的(就是分开后再压缩) 3.整体能压缩的
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int maxn=105;
//int slen[maxn][maxn];
string dp[maxn][maxn],str;
//计算重复的最小长度
int fold(const string &s){
int len=s.length();
for(int i=1;i*2<=len;++i){
if(len%i) continue;
bool isFold=true;
for(int j=0;j<len-i;++j){
if(s[j]!=s[j+i]){
isFold=false;
break;
}
}
if(isFold) return i;
}
return 0;
}
//折叠分为三种情况 1.不能折叠 2.部分折叠 3.整体都能折叠
int DFS(int left,int right){
string &ans=dp[left][right];
if(ans!="") return ans.length();
if(left==right) {
ans=str.substr(left,1);
return ans.length();
}
//分开,处理1,2情况,不能折叠,部分折叠
for(int i=left;i<right;++i){
int t1=DFS(left,i),t2=DFS(i+1,right);
if(ans.empty() || t1+t2<ans.length()){
ans=dp[left][i]+dp[i+1][right];
}
}
//处理情况三,整体折叠
int t=fold(str.substr(left,right-left+1));
if(t){
string tstr=to_string((right-left+1)/t)+"("+dp[left][left+t-1]+")";
if(ans.empty() || tstr.length()<ans.length()){
ans=tstr;
}
}
return ans.length();
}
int main(void){
while(cin>>str){
// memset(slen,-1,sizeof(slen));
int len=str.length();
for(int i=0;i<=len;++i){
for(int j=0;j<=len;++j){
dp[i][j]="";
}
}
DFS(0,len-1);
cout<<dp[0][len-1]<<endl;
}
}
减少了字符串的变化,优化时间
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int maxn=105;
int slen[maxn][maxn]; //slen[left][right]是[left,right]压缩后的最小长度
string dp[maxn][maxn],str;
//计算重复的最小长度
int fold(const string &s){
int len=s.length();
for(int i=1;i*2<=len;++i){
if(len%i) continue;
bool isFold=true;
for(int j=0;j<len-i;++j){
if(s[j]!=s[j+i]){
isFold=false;
break;
}
}
if(isFold) return i;
}
return 0;
}
//折叠分为三种情况 1.不能折叠 2.部分折叠 3.整体都能折叠
int DFS(int left,int right){
int &ans=slen[left][right];
if(ans>=0) return ans;
string &ansstr=dp[left][right];
if(left==right) {
ans=1;
ansstr=str.substr(left,1);
return ans;
}
//分开,处理1,2情况,不能折叠,部分折叠
int t=0;
ans=100000;
for(int i=left;i<right;++i){
int t1=DFS(left,i),t2=DFS(i+1,right);
if(t1+t2<ans){
ans=t1+t2;
t=i;
}
}
ansstr=dp[left][t]+dp[t+1][right];
//处理情况三,整体折叠
t=fold(str.substr(left,right-left+1));
if(t){
string tstr=to_string((right-left+1)/t)+"("+dp[left][left+t-1]+")";
if(tstr.length()<ans){
ans=tstr.length();
ansstr=tstr;
}
}
return ans;
}
int main(void){
while(cin>>str){
memset(slen,-1,sizeof(slen));
int len=str.length();
// for(int i=0;i<=len;++i){
// for(int j=0;j<=len;++j){
// dp[i][j]="";
// }
// }
DFS(0,len-1);
cout<<dp[0][len-1]<<endl;
}
}