题目描述
给出一个长度不超过 200 的由小写英文字母组成的字母串(该字串以每行 20 个字母的方式输入,且保证每行一定为 20 个)。要求将此字母串分成 k份,且每份中包含的单词个数加起来总数最大。
每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串 this 中可包含 this 和 is,选用 this 之后就不能包含 th。
单词在给出的一个不超过 6 个单词的字典中。
要求输出最大的个数。
输入格式
每组的第一行有两个正整数 p,k。 p 表示字串的行数,k 表示分为 k 个部分。
接下来的 p 行,每行均有 20 个字符。
再接下来有一个正整数 s,表示字典中单词个数。 接下来的 s 行,每行均有一个单词。
输出格式
1个整数,分别对应每组测试数据的相应结果。
解题思路
这题用两个动态规划就可以解决了,我还多用了一个滚动数组。
第一步是输入,这个是必须要做的,没啥说的,输入p,k。根据p按行输入一个字符串str,然后 int len=str.size()一下,这个后面要用的,之后输入s,再输入一个word数组。
之后是预处理,用w[i][j]表示str从i到j中单词个数。先构造出w[i][i],之后递推式:w[i-1][j]=w[i][j],如果str中从i-1到j的子串中存在一个单词从i-1位置开始,那么w[i-1][j]再加一。这里可以用string类的find函数,返回值是0的话就加一。用f[i][j]表示把前i个字符分成j段最多的单词个数,要先处理f[i][i],
f
[
i
]
[
i
]
=
∑
k
=
1
i
w
[
k
]
[
k
]
f[i][i]=\sum_{k=1}^{i}w[k][k]
f[i][i]=∑k=1iw[k][k],之后就是一个递推式f[i][j]=max(f[i][j],f[r][j-1]+w[r+1][i]),这里的r满足
(
j
−
1
)
≤
r
≤
(
i
−
1
)
(j-1)\le r\le (i-1)
(j−1)≤r≤(i−1)。
最后一步就是输出,输出f[len][k]就好了。
为什么要用到滚动数组呢,请看f数组部分,第k列只与第k-1列有关,同理,第k-1列只与第k-2列有关···那么我们就可以建立一个滚动数组,同时有个小技巧,f数组的第k列我们只取了f[len][k],其它都是没用的,所以我们滚动数组处理的时候只要处理到k-1步就可以了,第k简化成只求一个数了。
Talking is cheap,show you my code.
代码
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string str = "";
int p, k, s;
string word[6];
int w[202][202];
int f[202][2];
int check(string st) {
for (int i = 0;i < s;i++) {
if (st.find(word[i]) == 0) {
return 1;
}
}
return 0;
}
int main() {
cin >> p >> k;
for (int i = 0;i < p;i++) {
string st;
cin >> st;
str = str + st;
}
cin >> s;
for (int i = 0;i < s;i++) {
cin >> word[i];
}
int len = str.size();
for (int i = 1;i <= len;i++) {
for (int j = i;j > 0;j--) {
w[j][i] = w[j + 1][i];
bool flag = false;
string st = str.substr(j - 1, i - j + 1);
w[j][i] += check(st);
}
}
bool b = 0;
for (int i = 1;i <= len;i++) {
f[i][b] = w[1][i];
}
for (int cs = 2;cs < k;cs++) {
for (int i = cs;i <= len;i++) {
f[i][!b] = 0;
for (int j = cs - 1;j < i;j++) {
f[i][!b] = max(f[i][!b], f[j][b] + w[j + 1][i]);
}
}
b = !b;
}
int ans = 0;
for (int i = (k - 1);i < len;i++) {
ans = max(ans, f[i][b] + w[i + 1][len]);
}
cout << ans << endl;
return 0;
}