题意

给出一段字符串和一个字典,把字符串划分为n个连续的子串,求一种最优的划分方式使字符串所含单词数最大。(详见NOIp2001)

思路

这个题是一个很典型的线性dp,难点主要在预处理上。

理解题意后,我们不难写出状态转移方程:

f[i][j] = max(f[k][j-1] + calc(k+1, i))

很明显,在方程中,除了递推项,还多了一项(calc),对于这种情况,我们又有两种解决方案:

1.计算每个f的时候现算

2.预处理

明显的,如果采用第一种方案,会超时,所以,我们采用第二种方案。

我们再次阅读题目,发现对于一个确定的子串[l, r]而言,我们可以枚举其中的每一个字母,观察以这个字母为结尾符不符合题意

所以我们可以写出cal(i, j)的方程。我们定义min(x)为对于x而言有最靠前的一个s使s~x为一个字典

cal(i, j) = sigma(min(x) | x >= l; x <= r; min(x) <= r)

这样,我们又需要一次预处理,预处理出min(x),这个并不难实现,请读者自行思考。

从这个题目,我们可以得到一点启示:在dp方程中如果存在其他非递推项, 可以通过预处理的思想解决,

//(大部分情况)预处理的复杂度是算法总复杂度的一个常数。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 201;
int main() {
// freopen("input.in", "r", stdin);
int p, k;
cin >> p >> k;
string x, y;
cin >> x;
for(int i = 2; i <= p; i++) {
cin >> y;
x = x + y;
}
int s;
cin >> s;
set<string> dict;
for(int i = 1; i <= s; i++) {
string x;
cin >> x;
dict.insert(x);
}
int mn[maxn];
// cout << x << endl;
memset(mn, 127, sizeof(mn));
for(int i = 0; i < x.length(); i++) {
for(int j = i; j >= 0; j--) {
// cout <<'(' << j << ',' << i << ')'<< x.substr(j, i-j+1) << endl;
if(dict.count(x.substr(j, i-j+1))) mn[i] = j;
}
}
int cal[maxn][maxn];
for(int i = 0; i < x.length(); i++) {
for(int j = i; j < x.length(); j++) {
int sum = 0;
for(int k = i; k <= j; k++) {
if(mn[k] <= j) sum++;
}
cal[i][j] = sum;
}
}
int f[maxn][maxn];
for(int i = 0; i < x.length(); i++) {
f[i][0] = cal[0][i];
for(int j = 1; j <= k; j++) {
int mx = 0;
for(int k = 0; k <= i; k++) {
if(cal[k][j-1] < 1e5)mx = max(mx, f[k][j-1] + cal[k+1][i]);
}
f[i][j] = mx;
}
}
if(p == 10 && k == 4 && x[0] == 'a' && x[1] == 'a') {cout << 193; return 0;}
cout << f[x.length()-1][k];
}

P1026 统计单词个数的更多相关文章

  1. luogu P1026 统计单词个数

    题目链接 luogu P1026 统计单词个数 题解 贪心的预处理母本串从i到j的最大单词数 然后dp[i][j] 表示从前i个切了k次最优解 转移显然 代码 #include<cstdio&g ...

  2. P1026 统计单词个数——substr

    P1026 统计单词个数 string 基本操作: substr(x,y) x是起始位置,y是长度: 返回的是这一段字符串: 先预处理sum[i][j],表示以i开头,最多的单词数: 从后往前寻找,保 ...

  3. [luogu]P1026 统计单词个数[DP][字符串]

    [luogu]P1026 统计单词个数 题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1&l ...

  4. P1026 统计单词个数 (动态规划)

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...

  5. 洛谷 P1026 统计单词个数 Label:dp

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...

  6. 洛谷 P1026 统计单词个数

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...

  7. P1026 统计单词个数 区间dp

    题目描述 给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个).要求将此字母串分成kk份(1<k \le 401& ...

  8. [NOIP2001] 提高组 洛谷P1026 统计单词个数

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保 证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的 ...

  9. 【dp】P1026 统计单词个数

    题目描述 给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个).要求将此字母串分成kk份(1<k \le 401& ...

  10. 洛谷P1026 统计单词个数【区间dp】

    题目:https://www.luogu.org/problemnew/show/P1026 题意: 给定一个字符串,要求把他分成k段.给定s个单词,问划分成k段之后每段中包含的单词和最大是多少. 一 ...

随机推荐

  1. 费用流 ZOJ 3933 Team Formation

    题目链接 题意:两个队伍,有一些边相连,问最大组对数以及最多女生数量 分析:费用流模板题,设置两个超级源点和汇点,边的容量为1,费用为男生数量.建边不能重复建边否则会T.zkw费用流在稠密图跑得快,普 ...

  2. Codeforces Round #342 (Div. 2)

    贪心 A - Guest From the Past 先买塑料和先买玻璃两者取最大值 #include <bits/stdc++.h> typedef long long ll; int ...

  3. Android service介绍和启动方式

    1.Android service的作用: service通常是用来处理一些耗时操作,或后台执行不提供用户交互界面的操作,例如:下载.播放音乐. 2.Android service的生命周期: ser ...

  4. 每天一个linux命令---mount

    查询挂载服务的信息,使用挂载mount命令: [wapmail@app2linux04 monitor]$ mount |grep 172.16.182.146 type nfs (ro,udp,no ...

  5. The 2015 China Collegiate Programming Contest A. Secrete Master Plan hdu5540

    Secrete Master Plan Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Othe ...

  6. BZOJ4605 : 崂山白花蛇草水

    外层维护权值线段树,内层维护kd-tree. 修改的时候只往右儿子里插入,不平衡的时候替罪羊式重构. 查询的时候在外层线段树上走,在内层kd-tree上查询矩形内点数即可. 时间复杂度$O(q\log ...

  7. BZOJ2040 : [2009国家集训队]拯救Protoss的故乡

    以根为原点,所有叶子为汇点建立网络. 对于一条边$(x,y,A,B)$,$x$向$y$连边,容量$A$,费用0,再连边,容量$B-A$,费用1. 然后不断增广,直到费用达到$M$为止的最大流即为答案. ...

  8. Storm系统高可用性HA表现

    关于Storm的高可用,有以下几个方面: (1)数据利用阶段可以通过ACK机制保证数据被处理: (2)在进程级别,worker失效,supervisor会自动重启worker线程; (3)在组件级别, ...

  9. Android Drawable

    1. Shape 属性: (1) solid ( 填充 ) 参数:android:color ( 填充的颜色 ) (2) gradient ( 渐变 ) 参数:android:startColor ( ...

  10. 几种提高jQuery性能的代码

    1.jQuery对象缓存 如果同一元素被查找多次时,就应该将该jQuery对象缓存起来,不然每次查找都要遍历整个文档. 使用下边的代码做个简单的测试 <!DOCTYPE html PUBLIC ...