poj3267_dp

来源:互联网 发布:mysql更换引擎 编辑:程序博客网 时间:2024/05/21 20:22

题目描述:

   给出一个字典(包括序列单词);给出一个字符串,问该字符串最少删除多少个字母,才能都是由字典中的单词组成的。

 

解题思路:

  一开始当做回溯了。但是没有当做动规做来得好。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;  
}