题目给定一个字典,并给定一个字符串,要求出使该字符串为字典中单词序列所必需删除的最少字符数。动态规划求解
下面简单分析一下:
令dp[i]为使message中第i+1个位置字符开始到message结束的字符串满足题目要求所删除的最少字符数。则动态转移方程如下:
dp[i]=min{dp[i+1]+1,dp[pivot]+pivot-i-len}
分析如下:
1)当第i个字符无法匹配时,则dp[i]=dp[i+1]+1;
2)否则,我们可以将其舍弃也可以匹配,故可以得到dp[i]=min{dp[i+1]+1,dp[pivot]+pivot-i-len}
综合1)2)可得到动态转移方程
下面详细分析一下什么叫匹配:
匹配即以该字符为首字符,并可以在该字符串中找到若干字符组合成一个在字典中出现的单词,则匹配
下面是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 610
#define Maxx 310
#define Min(a,b) (a)<(b)?(a):(b)
char dic[Max][30];
char message[Maxx];
int dp[Maxx];
int W,L;
int main(){
scanf("%d%d",&W,&L);
getchar();
scanf("%s",message);
getchar();
for(int i=0;i<W;i++){
scanf("%s",dic[i]);
getchar();
}
dp[L]=0; // 初始化为0
int pivot,index; // 迭代器
for(int i=L-1;i>=0;i--){
dp[i]=dp[i+1]+1; // 状态1
for(int j=0;j<W;j++){ // 枚举每个单词,查看是否匹配
pivot=i,index=0;
int len=strlen(dic[j]);
while(pivot<L){ //此时匹配失败
if(message[pivot]==dic[j][index]) //若相等则迭代器均增加
pivot++,index++;
else // 否则只增加message迭代器
pivot++;
if(index==len){ // 匹配成功
dp[i]=Min(dp[i],dp[pivot]+pivot-i-index); //状态2
break;
}
}
}
}
printf("%d\n",dp[0]); // 输出结果
return 0;
}