题意
给出几个单词和一个句子,判断这几个单词变成这个句子的最小价值。每个单词变换的价值为:变换后的单词有多少位是和之前的单词不相同的。例如单词apple变成aplep,价值就是3,变成appel价值就是2。
思路
简单的动态转移方程,我们用f[i]代表用单词改到s[1~i]时的最小价值,显然得出f[i]=min(f[i],f[i-len[j]]+w),其中w为用这些单词改到s[i]的价值,len[j]为第j个单词的长度,f[句子的长度]就是答案。在计算价值的时候,我们可以用一个数组统计字母出现的次数,当在单词中出现我们可以给它+1,在句子中出现我们就可以给它-1,如果可以用单词替换的话,这个数组里的值都会是0,否则我们给w赋一个很大的值。
代码
#include<cstdio>
#include<cstring>
#define INF 214748364
int n,f[101],len[51],slen,sum[27];
char word[51][51],s[101];
int min(int x,int y) {return x<y?x:y;}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%s",word[i]);
len[i]=strlen(word[i]);//len[i]记录单词i的长度
}
scanf("%s",s);
slen=strlen(s);//slen是句子的长度
for (int i=0;i<slen;i++)//C++这里是从0开始的
{
f[i]=INF;//初始化,INF为一个很大的数
for (int j=1;j<=n;j++)
{
if (i<len[j]-1) continue;//如果当前枚举到的位置小于单词的长度就返回,因为这样替换不了
for (int d=1;d<=26;d++) sum[d]=0;//初始化桶
int w=0;//初始化价值
for (int k=0;k<len[j];k++)
{
if (s[i-len[j]+k+1]!=word[j][k]) w++;//计算价值
sum[word[j][k]-'a'+1]++;//出现了就+
sum[s[i-len[j]+k+1]-'a'+1]--;//出现了就-
}
for (int d=1;d<=26;d++) w=sum[d]!=0?INF:w;//如果桶有一个不为0说明不能从这个单词变到句子里,我们就让w=很大数
f[i]=min(f[i],f[i-len[j]]+w);//动态转移方程
}
}
if (f[slen-1]!=INF) printf("%d",f[slen-1]);
else printf("-1");//如果不能从单词变成句子我们就输出-1
}
本文介绍了一个字符串转换问题的解决思路及动态规划算法实现。通过计算单词间的字符差异,找到将一组单词转换为目标句子所需的最小成本。
129

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



