/*
solution:
转移方程类似lis的基本dp
d[i]表示从第i个位置到最后共有多少个最少可以删去的字符。题目所求结果就是d[0]
关于状态转移方程。一开始太过与拘泥与每一步来分析。其实完全可以只考虑一些 特殊
位置。比如只考虑在给出句子中与给出字典单词的首字母相同字符的位置。这样的话,
转移方程如下:
d[i] = d[i+1]+1; 在句子中所在位置的字符不是字典中任何一个单词的首字母情况
d[i] = min(d[i], d[pSentence]+(pSentence-i)-len)
匹配的过程是:当确认sentence第i位和某单词的首位吻合时,就开始逐字匹配,字符相同
则两个指针同时向后移动一次,否则pd固定,pm移动。当因为pm>L跳出匹配时,说明匹配
失败,dp[i]状态不变;当pd==单词长度时,单词匹配成功,进行dp[i]的状态优化.这样
(pSentence-i)-len就是在pSentence-i这一段中需要删除的字符数。
note:
date:
2016.8.18
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxl = 305;
char sentence[maxl]; //要解码的句子
char words[601][30]; //字典中的句子
int w, l, d[maxl]; //d[i]表示地i个
int main()
{
//freopen("input.txt", "r", stdin);
while(~scanf("%d%d", &w, &l)) { //w:字典里的单词个数。l:句子的长度
scanf("%s", sentence);
for(int i = 0; i < w; i++) scanf("%s", words[i]);
d[l] = 0;
for(int i = l-1; i >= 0; i--) {
d[i] = d[i+1] + 1;
for(int j = 0; j < w; j++) {
int len = strlen(words[j]);
if(sentence[i] == words[j][0] && l-i >= len) {
int pSentence = i, pWords = 0;
while(pSentence < l) {
if(words[j][pWords] == sentence[pSentence]) {
pSentence++; pWords++;
}
else pSentence++;
if(pWords == len) {
d[i] = min(d[i], d[pSentence]+(pSentence-i)-len);
}
}
}
}
}
//for(int i = 0; i < 10; i++) printf("%d ", d[i]); printf("\n");
printf("%d\n", d[0]);
}
return 0;
}
poj3267
最新推荐文章于 2018-10-29 22:04:13 发布