/*拿到这题已经好几天了,因为国庆放假回家,家里正好断网,一直没做,今天回到学
校终于把它做了。表示已经被dp虐了n久了,还是不得要领,只能守着dp的解题报告过日
子。T_T...
题意:给一个串mes[], 一个字典dic[],求让这个串完全匹配字典里的串时删除的最小元素
个数。
思路参考自:http://www.cnblogs.com/lyy289065406/archive/2011/07/31/2122638.html:
按mes[]串从后往前匹配,最坏的情况是 dp[i] = dp[i+1] + 1;
设 pm是mes[]的下标,如果出现从mes[i] 到 mes[pm] 这一段正好和dic[]里的一个串匹配,
则 dp[i] = min(dp[i], dp[pm] + pm - i - len)。(pm - i 表示这一段字串的长度,len表示dic[]
里与之匹配的串的长度。pm - i - len 就是[i, pm] 段成功匹配所删除的最小字符个数。)*/
MY CODE (141 MS):
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
const int N = 305;
int dp[N];
char mes[N];
string dic[N*2];
int main(){
//freopen("data.in", "r", stdin);
int n, l, i, j, len, pm, pd;
while(~scanf("%d%d", &n, &l)){
memset(mes, 0, sizeof(mes));
memset(dp, 0, sizeof(dp));
for(i = 0; i < N; i++){
dic[i].clear();
}
getchar();
for(i = 0; i < l; i++){
scanf("%c", &mes[i]);
}
for(i = 0; i < n; i++){
cin >> dic[i];
}
for(i = l-1; i >= 0; i--){
dp[i] = dp[i+1] + 1;
for(j = 0; j < n; j++){
len = dic[j].length();
if(len <= l && dic[j][0] == mes[i]){ //这里做一下修改,将原来的len < l - 1 改为len <= l。因为字典里出现的单词可能跟牛说的完全一样,这时结果为0(2012/03/09));
pm = i;
pd = 0;
while(pm < l){
if(dic[j][pd] == mes[pm])
pd++;
pm++;
if(pd == len){
dp[i] = min(dp[i], dp[pm] + pm - i - len);
}
}
}
}
}
printf("%d\n", dp[0]);
}
return 0;
}