2001 提高组 统计单词个数

题目描述

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

单词在给出的一个不超过 66 个单词的字典中。

要求输出最大的个数。

输入输出格式

输入格式:

 

每组的第一行有 22 个正整数( p,kp,k )

pp 表示字串的行数, kk 表示分为 kk 个部分。

接下来的 pp 行,每行均有 2020 个字符。

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

接下来的 ss 行,每行均有 11 个单词。

 

输出格式:

 

11 个整数,分别对应每组测试数据的相应结果。

 

输入输出样例

输入样例#1: 复制

1 3
thisisabookyouareaoh
4
is
a
ok
sab

输出样例#1: 复制

7

说明

this/isabookyoua/reaoh

 

#include<bits/stdc++.h>
using namespace std;
int p,k,i,j,l,r,n,m,len[210],dp[210][210][50];
string t,s,word[10];
inline int read(){
    char c;
    int d=0,w=1;
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    while(c>='0'&&c<='9'){d=d*10+c-'0';c=getchar();}
    return d*w;
}
int main(){
    p=read();k=read();
    m=p*20;s=" ";
    while(p--){
        cin>>t;
        s+=t;
    }
    n=read();
    for(i=1;i<=n;i++)
        cin>>word[i];
    memset(len,0x3f,sizeof(len));
    for(i=1;i<=m;i++)
        for(j=1;j<=n;j++)
            if(s.substr(i,word[j].size())==word[j])
                if(len[i]>word[j].size())len[i]=word[j].size();
    for(l=1;l<=m;l++)
        for(r=1;r<=m;r++)
            for(i=l;i<=r;i++)
                dp[l][r][1]+=i+len[i]-1<=r;
    for(i=2;i<=k;i++)
        for(l=m;l>=1;l--)
            for(r=l;r<=m;r++)
                for(j=l+i-1;j<r;j++)
                    if(dp[l][j][i-1]+dp[j+1][r][1]>dp[l][r][i])
                        dp[l][r][i]=dp[l][j][i-1]+dp[j+1][r][1];
    cout<<dp[1][m][k]<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值