hdu4843 [noi2000] 古城之谜 (Trie+dp)

解决hdu4843问题的关键在于理解和转化递归定义的名词短语与动词短语。通过定义四种词性状态,运用动态规划求解最小单词数。利用Trie树优化搜索,同时采用滚动数组降低时间复杂度。最终找到构成句子的最小单词数与句子数。
摘要由CSDN通过智能技术生成

做出这道题关键在于理解语法。其中名词短语和动词短语给出的都是递归定义,可以转化为更直观的,
<名词短语> ::= {<辅词>} <名词>,
<动词短语> ::= {<辅词>} <动词>,
也就是以一个名词或动词结尾,前面可以加上任意多个辅词。而句子就是要以名词短语开头,后面的名词短语和动词短语交替出现。

分析出语法结构,就可以进行动态规划。定义词性
j={0,1,2,3}。
f[i][0][k]表示前i个字母,以i结尾的单词词性为n,构成了k个句子的最小单词数
f[i][1][k]表示前i个字母,以i结尾的单词词性为v,构成了k个句子的最小单词数
f[i][2][k]表示前i个字母,以i结尾的单词词性为a,后面该接v了,构成了k个句子的最小单词数
f[i][3][k]表示前i个字母,以i结尾的单词词性为a,后面该接n了,构成了k个句子的最小单词数
枚举可能以i结尾的单词,设它的词性为type,前一个单词结尾为j。则分类讨论f[i][0/1/2/3][k]可以由f[j][0/1/2/3][k/k-1]的哪些转移而来,具体可以见这个人的分析
找到最小的k,使得min{f[m,0,k],f[m,1,k]}有意义,则最小的句子数为k,单词数为min{f[m,0,k],f[m,1,k]}
时间复杂度为O(nm·maxlen),匹配单词的时候可以用Trie树,第三维状态必须使用滚动数组。
tips:滚动数组每次都要清inf。初值为f[0][0][0]=0

#include <cstring>
#include <cstdio>
#define N 1005
#define M 6000
#define inf 0x3f3f3f3f
int n,m,maxlen,word[M][22],f[M][4][2],p;//word[i][j]表示以i开头,长度为j的子串是否为单词以及词性 
//f[i][0][k]表示前i个字母,以i结尾的单词词性为n,构成了k个句子的最小单词数
//f[i][1][k]表示前i个字母,以i结尾的单词词性为v,构成了k个句子的最小单词数
//f[i][2][k]表示前i个字母,以i结尾的单词词性为a,后面该接v了,构成了k个句子的最小单词数
//f[i][3][k]表示前i个字母,以i结尾的单词词性为a,后面该接n了,构成了k个句子的最小单词数
char s[M];
bool blank=0;
inline int max(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值