洛谷P1026 统计单词个数【区间dp】
题目:https://www.luogu.org/problemnew/show/P1026
题意:
给定一个字符串,要求把他分成k段。给定s个单词,问划分成k段之后每段中包含的单词和最大是多少。
一个位置作为单词的开头只能计算一次。
思路:
如果仅仅是统计某一个区间内的最大单词数,这比较简单。每次从后往前推一个字符,如果这个字符是一个单词的开头,那么$cnt[i][j] = cnt[i+1][j]+1$
但是现在要分成$j$段,这是状态之一,另一个状态应该是已经考虑前$i$个字符。
也就是用$dp[i][j]$表示前$i$个字符划分成$j$段的最大单词数。
很显然$dp[i][j] = dp[d][j-1] + cnt[d +1][i]$,也就是说在$0~i$之间找到一个位置$d$,从这里断开,前面的组成$j-1$段,后面的作为一个新的段。
需要考虑的是,一个只有$i$个字符的字符串,最多只能划分成$i$段。
并且要注意当$j =1$时需要特殊处理。
#include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stack>
#include<queue>
#include<iostream> #define inf 0x7fffffff
using namespace std;
typedef long long LL;
typedef pair<string, string> pr; int p, k, s;
const int maxn = ;
string str;
string word[];
int cnt[maxn][maxn];
int dp[maxn][maxn]; int main()
{
scanf("%d%d", &p, &k);
for(int i = ; i < p; i++){
string tmp;
cin>>tmp;
str += tmp;
}
scanf("%d", &s);
for(int i = ; i <= s; i++){
cin>>word[i];
} int len = str.length(); for(int i = len - ; i >= ; i--){
for(int j = i; j >= ; j--){
for(int x = ; x <= s; x++){
int l = word[x].length();
if(str.substr(j, min(i - j + , l)) == word[x]){
cnt[j][i] = cnt[j + ][i] + ;
break;
}
else cnt[j][i] = cnt[j + ][i];
//cout<<str.substr(j, min(i - j + 1, l))<<" "<<cnt[j][i]<<endl;
} }
} for(int i = ; i <= k; i++){
dp[i][i] = dp[i - ][i - ] + cnt[i][i];
}
for(int i = ; i < len; i++){
dp[i][] = cnt[][i];
for(int j = ; j <= min(k, i); j++){
for(int d = j - ; d < i; d++){
dp[i][j] = max(dp[i][j], dp[d][j - ] + cnt[d + ][i]);
}
}
} printf("%d\n", dp[len - ][k]); return ;
}
洛谷P1026 统计单词个数【区间dp】的更多相关文章
- 洛谷 P1026 统计单词个数 Label:dp
题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...
- P1026 统计单词个数 区间dp
题目描述 给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个).要求将此字母串分成kk份(1<k \le 401& ...
- [NOIP2001] 提高组 洛谷P1026 统计单词个数
题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保 证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的 ...
- 洛谷 P1026 统计单词个数
题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...
- 洛谷 P1026 统计单词个数 (分组+子串预处理)(分组型dp再次总结)
一看完这道题就知道是划分型dp 有两个点要注意 (1)怎么预处理子串. 表示以i为开头,结尾在j之前(含),有没有子串,有就1,没有就0 (2)dp的过程 这种分成k组最优的题目已经高度模板化了,我总 ...
- [luogu]P1026 统计单词个数[DP][字符串]
[luogu]P1026 统计单词个数 题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1&l ...
- luogu P1026 统计单词个数
题目链接 luogu P1026 统计单词个数 题解 贪心的预处理母本串从i到j的最大单词数 然后dp[i][j] 表示从前i个切了k次最优解 转移显然 代码 #include<cstdio&g ...
- P1026 统计单词个数——substr
P1026 统计单词个数 string 基本操作: substr(x,y) x是起始位置,y是长度: 返回的是这一段字符串: 先预处理sum[i][j],表示以i开头,最多的单词数: 从后往前寻找,保 ...
- 【dp】P1026 统计单词个数
题目描述 给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个).要求将此字母串分成kk份(1<k \le 401& ...
随机推荐
- uva 1400 "Ray, Pass me the dishes!" (区间合并 最大子段和+输出左右边界)
题目链接:https://vjudge.net/problem/UVA-1400 题意:给一串序列,求最大子段,如果有多个,输出字典序最小的那个的左右端点 思路: 之前写过类似的,这个麻烦点需要输出左 ...
- [转帖]「知乎知识库」— 5G
「知乎知识库」— 5G 甜草莓 https://zhuanlan.zhihu.com/p/55998832 通信 话题的优秀回答者 已关注 881 人赞同了该文章 谢 知识库 邀请~本文章是几个答 ...
- CentOS7下使用Harbor搭建Docker私有仓库
相关资料: Harbor官方网站:https://goharbor.io/ Harbor Github地址:https://github.com/goharbor/harbor ⒈安装Docker(必 ...
- HDU - 2196(树形DP)
题目: A school bought the first computer some time ago(so this computer's id is 1). During the recent ...
- 集成板的CodeBlocks编译器配置相关文档
如需安装包请后台留言!! 原文链接:https://w.url.cn/s/A1RSfZP 打开安装包进行安装,除安装路径大家可以自行调整外, 其他默认即可.最后安装完成,CodeBlocks的大门即将 ...
- python经典小程序集锦(一) 实现九九乘法表
本篇文章主要是收集整理一些小程序以供大家娱乐,或者是在面试的时候使用到.文章会持续更新,希望大家收藏关注哦. 1.代码实现过程 for i in range(1, 10): for j in rang ...
- Partial的应用
Partial是局部类型的意思.允许我们将一个类.结构或接口分成几个部分,分别实现在几个不同的.cs文件中.C#编译器在编译的时候仍会将各个部分的局部类型合并成一个完整的类 局部类型的注意点1. 局部 ...
- Web API 自动生成接口文档
1.添加NuGet程序包 Microsoft ASP.NET Web API 2.2 Help Page (这是微软官方的) A Simple Test Client for ASP.NET ...
- 【原创】编程基础之Jekins
Jenkins 2.164.2 官方:https://jenkins.io 一 简介 Build great things at any scale The leading open source a ...
- react用高阶组件实现路由守卫
react-router不像vue-router一样有很多钩子函数,可以做路由守卫.想实现路由守卫,可以用高阶组件来实现. @connect(state => ({ isLogin: state ...