题目描述
给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。
单词在给出的一个不超过6个单词的字典中。
要求输出最大的个数。
输入输出格式
输入格式:
每组的第一行有二个正整数(p,k)
p表示字串的行数;
k表示分为k个部分。
接下来的p行,每行均有20个字符。
再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)
接下来的s行,每行均有一个单词。
输出格式:
一个整数,分别对应每组测试数据的相应结果。
输入输出样例
说明
this/isabookyoua/reaoh
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define inf 2147483647 const ll INF = 0x3f3f3f3f3f3f3f3fll; #define ri register int template <class T> inline T min(T a, T b, T c) { return min(min(a, b), c); } template <class T> inline T max(T a, T b, T c) { return max(max(a, b), c); } template <class T> inline T min(T a, T b, T c, T d) { return min(min(a, b), min(c, d)); } template <class T> inline T max(T a, T b, T c, T d) { return max(max(a, b), max(c, d)); } #define pi acos(-1) #define me(x, y) memset(x, y, sizeof(x)); #define For(i, a, b) for (int i = a; i <= b; i++) #define FFor(i, a, b) for (int i = a; i >= b; i--) #define mp make_pair #define pb push_back const int maxn = 100005; #define mod 100003 const int N=200; // name******************************* char a[210]; char word[210][210]; bool vis[mod]; int n,m; int sum[210][210]; int p,K; bool v[210]; int f[210][210]; // function****************************** int Hash(char *str) { int k=0,ln=strlen(str+1); For(i,1,ln) { k=k*29+str[i]; k%=mod; } return k; } //*************************************** int main() { // freopen("test.txt", "r", stdin); scanf("%d%d",&p,&K); int c=1; For(i,1,p) { scanf("%s",a+c); c+=20; } n=p*20; scanf("%d",&m); For(i,1,m) { scanf("%s",word[i]+1); int h=Hash(word[i]); if(vis[h])i--,m--; else vis[h]=1; } For(i,1,n) { For(j,i,n) { me(v,0); For(k,1,m) { int ln=strlen(word[k]+1); For(l,i,j+1-ln) { if(v[l])continue; bool flag=0; For(r,1,ln) { if(a[l+r-1]!=word[k][r]) { flag=1; break; } } if(!flag)sum[i][j]++,v[l]=1; } } } } For(i,1,n) For(k,1,K) For(j,k-1,i-1){ f[i][k]=max(f[i][k],f[j][k-1]+sum[j+1][i]); } cout<<f[n][K]; return 0; }