Problem Address:http://poj.org/problem?id=3267
【思路】
一道动态规划的题目。
dp[i]表示对于message的第i位,需要删除的最小字符数。
对于dp[i],枚举字典里的每个单词,从该点往前匹配,查询是否可以匹配。
如果不行,则返回i。
如果可以匹配,则返回当前删除的字符数与单词最后匹配位置的dp值之和。
同时,需要比较dp[i-1]+1,表示如果只是删除当前字符。
最后返回dp[l]。
【代码】
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 600;
const int maxl = 300;
char mesg[maxl+5];
char word[maxn+5][30];
int len[maxn+5];
int dp[maxl+5];
inline int match(int length, char *str, int end)
{
int i, j;
for (i=end-1,j=length-1; i>=0 && j>=0; i--)
{
if (mesg[i]==str[j]) j--;
}
if (j<0) return dp[i+1]+end-i-1-length;//i+1为最终匹配位置,i为最终匹配位置的前一个位置。由于这里我的dp标号是从1开始的,所以需要用i+1来处理。
else return end;
}
int main()
{
int w, l;
int i, j;
int min, temp;
scanf("%d %d", &w, &l);
scanf("%s", mesg);
for (i=0; i<w; i++)
{
scanf("%s", word[i]);
len[i] = strlen(word[i]);
}
dp[0] = 0;
for (i=1; i<=l; i++)
{
min = dp[i-1]+1;
for (j=0; j<w; j++)
{
temp = match(len[j], word[j], i);
if (temp<min)
min = temp;
}
dp[i] = min;
}
printf("%d\n", dp[l]);
return 0;
}