Few know that the cows have their own dictionary with W (1 ≤ W ≤ 600) words, each containing no more 25 of the characters 'a'..'z'. Their cowmunication system, based on mooing, is not very accurate; sometimes they hear words that do not make any sense. For instance, Bessie once received a message that said "browndcodw". As it turns out, the intended message was "browncow" and the two letter "d"s were noise from other parts of the barnyard.
    The cows want you to help them decipher a received message (also containing only characters in the range 'a'..'z') of length L (2 ≤ L ≤ 300) characters that is a bit garbled. In particular, they know that the message has some extra letters, and they want you to determine the smallest number of letters that must be removed to make the message a sequence of words from the dictionary.

       开始的时候觉得很难,后来仔细思考之后才发现切入点,重要的还是看出一个合适的子问题,总之DP题目就得多练才能出眼光。
       设dp[i]为前i个字符转为合法所需删除的字母个数,那么当我们递推dp[i+1]的时候,实际上就是尝试寻找一个字典里的串,它也以sourc[i+1]收尾(有的做法是以i字母打头往前推),那么这时候dp[i+1]需要知道的就是 dp[i-(cnt+w[j])]处的结果,cnt+w[j]是倒退的长度,这个长度包含了某个合法串长度w[j]和cnt个被删除的字符,此时推得一个临时解,所有字典单词推出的临时解中最小的一个转移之。
      转移方程:DP[i]=Min{ DP[i] ,DP[i-(cnt+w[k])]+cnt ,DP[i-1]+1 }

 1#include<iostream>
 2#include<cstring>
 3using namespace std;
 4#define MIN(a,b) (a<b)?a:b
 5#define L 301
 6#define W 601
 7int dp[L];
 8int lenArr[W];
 9char sourc[L+1];
10char dic[W][27];
11int main(){
12    int i,j,k;
13    int l,w;
14    int souPoi,dicPoi,cnt;
15    while(cin>>w>>l){
16        cin>>sourc;
17        for(i=0;i<w;i++){ cin>>dic[i]; lenArr[i]=strlen(dic[i])-1; }
18
19        for(i=0;i<=l;i++) dp[i]=0x7fffffff;
20        dp[0]=0;
21        for(i=1;i<=l;i++){
22            for(j=0;j<w;j++){
23                dicPoi=lenArr[j];
24                souPoi=i-1;
25                cnt=0;
26                /* 倒退匹配,若当前不匹配,则尝试删去一个字符 */
27                while( souPoi>-1 && dicPoi>-1 ){
28                    if( sourc[souPoi] == dic[j][dicPoi] )--souPoi; --dicPoi; }
29                    else++cnt; --souPoi; }
30                }

31                if( dicPoi<0 ){ dp[i]=MIN(dp[i],dp[i-(cnt+lenArr[j]+1)]+cnt); }
32                else{ dp[i]=MIN(dp[i],dp[i-1]+1); }   /* 匹配失败 */
33            }

34        }

35
36        printf("%d\n",dp[l]);
37    }

38    return 0;
39}