刚看到这个题一直在纠结怎么划分成k份再转移,事实证明我想多了
先预处理出数组w[I][j],表示从i到j的单词个数,如果有多个以i开头的单词,只统计一次即可
dp[I][j]表示从0到i划分成j份,则
dp[I][j]=max(dp[k][j-1]+w[k+1][j]|j-1<=k<i)
顺便%一下用贪心A掉此题的ZY大神
#include<iostream>
#include<cstring>
#include<string>
#define f dp
#define maxn 200+2
#define maxk 40+2
#define maxs 6+2
using namespace std;
string dic[maxs],a;
int p,k,s,dp[maxn][maxk];//表示从0到i分成j份
int w[maxn][maxn];//表示从i到j有w[i][j]个单词
void init(void){
cin>>p>>k;
string temp;
a+='0';
for(int i=0;i<p;i++){
cin>>temp;
a+=temp;
}
cin>>s;
for(int i=1;i<=s;i++)
cin>>dic[i];
memset(dp,0,sizeof(dp));
memset(w,0,sizeof(w));
for(int i=p*20;i>0;i--){
for(int j=i;j<=p*20;j++){//枚举字符
for(int k0=1;k0<=s;k0++){//枚举单词
if(a.find(dic[k0],i)==i&&dic[k0].length()<=j-i+1){
w[i][j]++;
break;
}
}
w[i][j]+=w[i+1][j];
}
}
/*for(int i=1;i<=p*20;i++){
dp[i][i]=
}*/
return;
}
int main(){
init();
//dp[i][j]=max(dp[k][j-1]+w[k+1]|k>=j-1)
for(int i=1;i<=p*20;i++){
for(int j=1;j<=i&&j<=k;j++){
int temp=0;
for(int k0=j-1;k0<i;k0++)
temp=max(temp,dp[k0][j-1]+w[k0+1][i]);
dp[i][j]=temp;
}
}
cout<<dp[p*20][k];
return 0;
}
本文介绍了一种使用动态规划解决字符串划分问题的方法。通过预处理数组记录子串中不同单词的数量,利用DP状态转移方程求解最优解。适用于需要高效处理大量字符串数据的应用场景。
759

被折叠的 条评论
为什么被折叠?



