题目链接:http://poj.org/problem?id=3267
题目:给出一个字典和一个字符串,问这个字符串中最少删去几个字符,能使它变成由字典中的单词组成的序列。
分析:从字符串的第一个字符开始,在字典中依次寻找与其匹配的单词:
dp[i] = min( dp[i], dp[ i - 1] + 1 ); 如果找不到匹配单词
dp[i] = min( dp[i], dp[ i - ( len[j] + cnt ) ] + cnt ); 如果第 j 个单词与其匹配
dp[i] 代表到字符串第 i 个字母时需要删去多少个字符,len[j]是字典中第 j 个单词的长度,cnt 是如果字符串与该单词匹配需要删去的字母数目。
字典中可能有不止一个单词与字符串匹配,应当选择删去字母数最小的那个。
1 #include <cstdio> 2 #include <cstring> 3 4 const int INF = 2147483647; 5 6 int dp[310]; 7 int len[610]; 8 char dictionary[610][30]; 9 char str[310]; 10 int W, L; 11 12 int min( int a, int b ) 13 { 14 return a < b ? a : b; 15 } 16 17 int DP() 18 { 19 for ( int i = 1; i <= L; i++ ) 20 dp[i] = INF; 21 22 dp[0] = 0; 23 24 for ( int i = 1; i <= L; i++ ) 25 { 26 for ( int j = 0; j < W; j++ ) 27 { 28 int cnt = 0; //匹配当前单词需要删去的字母个数 29 int dic_i = len[j] - 1; 30 int str_i = i - 1; 31 32 while ( str_i > -1 && dic_i > -1 ) //从后往前匹配 33 { 34 if ( str[str_i] == dictionary[j][dic_i] ) 35 { 36 --str_i; 37 --dic_i; 38 } 39 else 40 { 41 --str_i; 42 ++cnt; 43 } 44 } 45 46 if ( dic_i < 0 ) //如果匹配成功 47 dp[i] = min( dp[i], dp[ i - ( len[j] + cnt ) ] + cnt ); 48 else dp[i] = min( dp[i], dp[i - 1] + 1 ); //如果匹配失败 49 } 50 } 51 52 return dp[L]; 53 } 54 55 int main() 56 { 57 while ( scanf( "%d%d", &W, &L ) != EOF ) 58 { 59 scanf( "%s", str ); 60 for ( int i = 0; i < W; i++ ) 61 { 62 scanf( "%s", dictionary[i] ); 63 len[i] = strlen( dictionary[i] ); 64 } 65 66 printf( "%d\n", DP() ); 67 } 68 return 0; 69 }