题目描述
给出一个长度不超过 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;
}