【划分型DP】统计单词个数

来源:互联网 发布:java string正则表达式 编辑:程序博客网 时间:2024/06/05 14:29


题目描述 Description

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

输入描述 Input Description

第一行为一个正整数(0<n<=5)表示有n组测试数据
每组的第一行有二个正整数(p,k)
p表示字串的行数;
k表示分为k个部分。
接下来的p行,每行均有20个字符。
再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)
接下来的s行,每行均有一个单词。

输出描述 Output Description

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


样例输入 Sample Input

1
1 3
thisisabookyouareaoh
4
is
a
ok
sab

样例输出 Sample Output

7

数据范围及提示 Data Size & Hint

this/isabookyoua/reaoh

//f[i][j]表示i->j区间有多少符合的单词//dp[i][j]表示前i个分成j段的最大值#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;int f[210][210], dp[210][210];int n, p, k, tot, s;string str2[50];char str[50][50], st[500];bool check(int x, int y) {for (int i = 0; i<str2[y].size(); i++)if (st[i + x] != str2[y][i]) return 0;return 1;}int main() {cin >> n;while (n--) {memset(dp, 0, sizeof(dp));memset(f, 0, sizeof(f));cin >> p >> k; tot = 0;for (int i = 1; i <= p; i++)cin >> str[i];cin >> s;for (int i = 1; i <= s; i++)cin >> str2[i];for (int i = 1; i <= p; i++)for (int j = 0; j<strlen(str[i]); j++)st[++tot] = str[i][j]; //st存储每个字母,tot为字母总数for (int i = 1; i <= tot; i++) {int l = 0;for (int j = 1; j <= s; j++)if (l<str2[j].size() && check(i, j))l = str2[j].size(); //前i个字母开始的最大匹配词,例:选用this之后不能选用thif (l>0) //找到匹配段for (int q = 1; q <= i; q++)for (int j = i + l - 1; j <= tot; j++)f[q][j]++;}//开始区间动态规划for (int i = 1; i <= tot; i++)for (int j = 1; j <= k&&j <= i; j++)for (int q = j - 1 >= 0 ? j - 1 : 1; q<i; q++)dp[i][j] = max(dp[q][j - 1] + f[q + 1][i], dp[i][j]);cout << dp[tot][k] << endl;}}

划分型DP需要注意的地方

若dp[i][j]表示为前i个分成j份时:


1.要考虑dp[0][0]=1;

2.k=1时无需状态转移,表示只有一种划分方案,需要if语句提前处理边界;

3.预处理时dp[][]=INF.

4.模板(答案为dp[N][M]时)

for(int i=1;i<=N;i++)                           for(int j=1;j<=min(i,M);j++)                                    for(int k=j-1;k<=i-1;k++)                                            d[i][j]=min(d[i][j],d[k][j-1](?)f(x));






0 0