题目描述:
给出一个字典(包括序列单词);给出一个字符串,问该字符串最少删除多少个字母,才能都是由字典中的单词组成的。
解题思路:
一开始当做回溯了。但是没有当做动规做来得好。dp[i]存str的前i个中,最少删除多少个字母才都由单词组成;那么dp[i+1] =min(dp[i] + 1,str[i+1]同某个单词尾部匹配计算出来的值),后者是由匹配中删除的字母数+匹配段前j个dp[j]组成。
代码:
#include <stdio.h>
#include <stdlib.h>
#define INFINITY 400
#define STRLEN 301
#define WORDLEN 30
#define DICLEN 700
typedef struct
{
char word[WORDLEN];
int len;
}DIC;
DIC dic[DICLEN];
int dp[STRLEN], word_num, str_len;
char str[STRLEN];
int dpDic(int str_index)
{
int i, word_index, sum , min =INFINITY, len = INFINITY, tmp = str_index;
//printf("dpDic:\n");
for(i=1;i<=word_num;i++)
{
word_index = dic[i].len-1;
if(dic[i].word[word_index] == str[str_index-1]) //继续找
{
len = INFINITY;
word_index --;
str_index --;
sum = 0;
while(word_index >= 0&& str_index>=0)
{
if(dic[i].word[word_index] == str[str_index-1] )
word_index --;
else
sum ++;
str_index --;
}
if(word_index == -1)
{
//printf("匹配单词表中的第%d个单词。\n",i);
len = sum + dp[str_index];
//printf("得到的若使用这个单词尾部匹配,则优值为sum(%d)+dp[%d](%d):%d\n",sum,str_index,dp[str_index],len);
}
}
if(len < min)
min = len;
str_index = tmp;
}
return min;
}
main()
{
int i, l;
scanf("%d%d",&word_num, &str_len);
scanf("%s",str);
for(i=1;i<=word_num;i++)
{
scanf("%s",dic[i].word);
dic[i].len = strlen(dic[i].word);
}
dp[0] = 0;
for(i=1;i<=str_len;i++)
{
l = dpDic(i);
//printf("dpDic(%d) = %d.\n",i,l);
if( l < dp[i-1]+1)
dp[i] = l;
else
dp[i] = dp[i-1] + 1;
// printf("dp[%d] = %d.\n",i,dp[i]);
}
printf("%d\n",dp[str_len]);
//system("pause");
return0;
}