您的位置:首页 > 其它

POJ 3267 The Cow Lexicon

2017-01-31 11:20 393 查看
http://poj.org/problem?id=3267

题意:给出一个序列和w个单词,计算至少需要删除多少个单词才能使该序列正好由给出的单词组成。

思路:虽说我知道这道题要用动态规划来做,但是转移方程实在是写不出来,还是依靠了别人的解题报告。

我们设dp(i)代表的是从i~L这部分序列中最少所要删除的单词数,初始化dp[L]=0。状态转移方程如下:



第一个很好理解,就是在不能匹配的情况下,在上一个的基础上多删除一个,也就是删除新加入的单词。

第二个有点复杂,len就是单词的长度,pm相当于是指向序列的指针,pm-i代表的是包含当前单词的序列的长度,因为当中可能还掺杂着别的一些单词,pm-i-len代表的就是多余单词的个数,也就是需要删除个数(比如说,当前序列为codw,比较单词为cow,pm-i=4,pm-i-len=1,也就是要删除d这一个多余的单词)。dp[pm]显然就是序列为pm~L时最少所要删除的单词数。

最后只要输出dp[0]就可以了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;

char words[605][30];
char mess[305];
int dp[305];

int main()
{
//freopen("D:\\txt.txt", "r", stdin);
int W, L;
while (cin >> W >> L && W && L)
{
cin >> mess;
for (int i = 0; i < W; i++)
{
cin >> words[i];
}
dp[L] = 0;
for (int i = L - 1; i >= 0; i--)
{
dp[i] = dp[i + 1] + 1;     //无法匹配时需要删除的字符数,先记录一下最坏情况
for (int j = 0; j < W; j++)
{
int len = strlen(words[j]);
if (len <= L - i && words[j][0] == mess[i])  //单词长度不能大于i~L字段的长度并且首字母得相同
{
int p1 = i;
int p2 = 0;

while (p1 < L)
{
if (mess[p1] == words[j][p2])
{
p1++;
p2++;
}
else  p1++;
if (p2 == len)
{
dp[i] = min(dp[i], dp[p1] + p1 - i - len);
break;
}
}
}

}

}
cout << dp[0] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: