ACM 94. [NOIP2001] 统计单词个数(划分dp)

来源:互联网 发布:ping地址命令 端口 编辑:程序博客网 时间:2024/05/16 19:04

94. [NOIP2001] 统计单词个数

★☆   输入文件:tjdcgs.in   输出文件:tjdcgs.out   简单对比
时间限制:1 s   内存限制:128 MB


Description

给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k≤40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。 单词在给出的一个不超过6个单词的字典中。要求输出最大的个数。

Input

(在正式输入前有一行一个1,代表数据组数)

第一行有2个正整数p,k。p表示字串的行数;k表示分为k个部分。

接下来的p行,每行均有20个字符。

再接下来有一个正整数s,表示字典中单词个数。(1≤s≤6)

接下来的s行,每行均有一个单词。

Output

仅一行,一个整数,表示划分出来的最多单词个数。

Sample Input

1

1 3

thisisabookyouareaoh

4

is

a

ok

sab

Sample Output

7

Hint

按如下方式划分字符串:

this/isabookyoua/reaoh


优化:预先把字典中的词语长度求出来
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define INF 9999999int T;int p,k;char readstr[1000];char text[1000];char dic[20][1000];int dcnt;int d[1000][21];int len[20];bool cmp(const char *a,const char *b){while(*b){if(!*a) return false;if(*a!=*b) return false;a++;b++;}return true;}int GetCount(int s,int t){int cnt=0;for(int i=s;i<=t;i++){for(int j=0;j<dcnt;j++) if(t-i+1>=len[j] && cmp(&text[i],dic[j])){cnt++;break;}}return cnt;}int dp(int t,int k){int minx=0;if(t<k) return -INF;if(k==0){return GetCount(0,t);}if(d[t][k]>=0) return d[t][k];for(int i=0;i<t;i++){minx=max(minx,dp(i,k-1)+GetCount(i+1,t));}return d[t][k]=minx;}int main(){freopen("tjdcgs.in","r",stdin);freopen("tjdcgs.out","w",stdout);scanf("%d",&T);while(T--){scanf("%d%d",&p,&k);for(int i=0;i<p;i++){scanf("%s",readstr);strcat(text,readstr);}scanf("%d",&dcnt);for(int i=0;i<dcnt;i++){scanf("%s",dic[i]);len[i]=strlen(dic[i]);}memset(d,-1,sizeof(d));cout<<dp(strlen(text)-1,k-1)<<endl;}return 0;}


0 0
原创粉丝点击