T3

题目描述

给出一个长度不超过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行,每行均有一个单词。

输出格式:

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

输入输出样例

输入样例#1:

1 3
thisisabookyouareaoh
4
is
a
ok
sab
输出样例#1:

7

说明

this/isabookyoua/reaoh

思路:

  我们可以用DP+KMP来处理这道题

  首先需要知道题目要求是:

      不能以同一个开头生成两个单词

  千万别理解错意思、、、

  由于在拆分字符串的过程中,如果以某位置为首某个较短单词被截断,那么以该位置为首的较长单词必然也会被截断。

    也就是说,对于各个位置来说我们选取较短的单词总不会比选取较长的单词所形成的单词少。

  那么题目就转化成了在每一个位置上选取能够形成的最短的单词,如果不能形成则为0,直接continue即可

  DP转移方程也是很好想的:

      if(dp[x][j-1])

        dp[i][j]=max(dp[i][j],dp[x][j-1]+KMP(x+1,i));//其中x是我们枚举的划分位置的前一个字符

坑点:

  注意题目要求的读入方式

上代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int L1 = ;
const int L2 = ;
int len;
char a[L1];
void init(int T) {
char c;
while(T--) {
for(int i=; i<; i++) {
scanf(" %c",&c);
a[len++]=c;
}
}
} char d[L2][L1]; //存字典
int sum,cnt;
//sum:统计一段单词中可以匹配的总个数
//cnt:字典单词总个数
int nxt[L2][L1],nowx[L2],dl[L2];
//nxt[]:开两维的原因是因为----不止一个模式串要跟文本串进行匹配
//nowx[]:每个单词当前在KMP函数中匹配的位数
//dl[]:字典中每个单词的长度
bool vis[L1]; //判重
int KMP(int l,int r) {
sum=;
memset(vis,false,sizeof(vis));
memset(nowx,,sizeof(nowx));
for(int i=l; i<=r; i++)
for(int j=; j<cnt; j++) {
while(nowx[j] && a[i]!=d[j][nowx[j]])
nowx[j]=nxt[j][nowx[j]];
if(a[i]==d[j][nowx[j]]) nowx[j]++;
if(nowx[j]==dl[j] && !vis[i-dl[j]+]) { //匹配成功
vis[i-dl[j]+]=true; //标记开头
sum++;
}
}
return sum;
} int dp[L1][L1];
int main() {
int p,k,x;
scanf("%d%d",&p,&k);
init(p);
scanf("%d",&cnt);
for(int i=; i<cnt; i++) {
scanf("%s",d[i]);
dl[i]=strlen(d[i]);
}
for(int i=; i<cnt; i++) {
x=;
nxt[i][x]=nxt[i][x+]=;
for(int j=; j<dl[i]; j++) {
while(x && d[i][x]!=d[i][j]) x=nxt[i][x];
nxt[i][j+]=d[i][x] == d[i][j] ? ++x : ;
}
}
for(int i=; i<len; i++) {
for(int j=; j<=k; j++) {
if(j==) dp[i][j]=KMP(,i);
else {
for(x=; x<i; x++)
if(dp[x][j-])
dp[i][j]=max(dp[i][j],dp[x][j-]+KMP(x+,i));
}
}
}
printf("%d",dp[len-][k]);
return ;
}

Noip2001 提高组 T3的更多相关文章

  1. 洛谷 P1025 & [NOIP2001提高组] 数的划分(搜索剪枝)

    题目链接 https://www.luogu.org/problemnew/show/P1025 解题思路 一道简单的dfs题,但是需要剪枝,否则会TLE. 我们用dfs(a,u,num)来表示上一个 ...

  2. JZOJ2020年8月11日提高组T3 页

    JZOJ2020年8月11日提高组T3 页 题目 Description 战神阿瑞斯听说2008年在中华大地上,将举行一届规模盛大的奥林匹克运动会,心中顿觉异常兴奋,他想让天马在广阔的天空上,举行一场 ...

  3. 【GDKOI2014】JZOJ2020年8月13日提高组T3 壕壕的寒假作业

    [GDKOI2014]JZOJ2020年8月13日提高组T3 壕壕的寒假作业 题目 Description Input Output 输出n行.第i行输出两个整数,分别表示第i份作业最早完成的时刻以及 ...

  4. JZOJ2020年8月10日提高组T3 玩诈欺的小杉

    JZOJ2020年8月10日提高组T3 玩诈欺的小杉 题目 Description 是这样的,在小杉的面前有一个N行M列的棋盘,棋盘上有\(N*M\)个有黑白棋的棋子(一面为黑,一面为白),一开始都是 ...

  5. 【佛山市选2013】JZOJ2020年8月7日提高组T3 海明距离

    [佛山市选2013]JZOJ2020年8月7日提高组T3 海明距离 题目 描述 对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数.异或的规则为: 0 XOR 0 = 0 1 XOR ...

  6. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  7. [NOIP2001提高组]CODEVS1014 Car的旅行路线(最短路)

    最短路,这个不难想,但是要为它加边就有点麻烦..还好写完就过了(虽然WA了一次,因为我调试用的输出没删了..),不然实在是觉得挺难调的.. ------------------------------ ...

  8. 【NOIP2013提高组T3】加分二叉树

    题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...

  9. noip1998 提高组t3 挖地雷

    题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N<=20),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径.当地窖及其连接的数据给出之后,某人可以从任一处 ...

随机推荐

  1. [Office 365] Office 365与Visio 2013/2016兼容性测试

                  Visio Professional 2013 (x64) - (Chinese-Simplified) 详细信息 文件名 cn_visio_professional_20 ...

  2. Optional 理解

    目录 Optional 理解 1. 含义 2. Optional 类中方法 3. Optional 对象不应该作为方法参数 Optional 理解 1. 含义 Optional 是一个容器对象,该容器 ...

  3. 16-MySQL DBA笔记-调优基础理论和工具

    第五部分 性能调优与架构篇 本篇将为读者介绍性能调优的一些背景知识和理论,然后介绍一些工具的运用,最后介绍从应用程序到操作系统.到数据库.到存储各个环节的优化. 性能调优是一个高度专业的领域,它需要一 ...

  4. BOM与DOM的区别与联系

    一.BOM与DOM的区别 1.BOM(Browser Object Model) BOM 即浏览器对象模型,BOM没有相关标准,BOM的最核心对象是window对象.window对象既为javascr ...

  5. (三)Activiti之第一个程序以及Activiti插件的使用和Activiti表的解释

    一.案例 1.1 建立Activiti Diagram图 new -> activiti ->Activiti Diagram,创建一个HelloWorld文件,后缀自动为bpmn,如下图 ...

  6. (四)Redis之哈希

    一.哈希常用命令 赋值 取值 删除 增加数字 判断字段是否存在 获取hash属性个数 获取hash所有属性名称 1.2.3 赋值取值和删除 package myRedis01; import java ...

  7. DRF框架中链表数据通过ModelSerializer深度查询方法汇总

    DRF框架中链表数据通过ModelSerializer深度查询方法汇总 一.准备测试和理解准备 创建类 class Test1(models.Model): id = models.IntegerFi ...

  8. jQuery_了解jQuery

  9. 数组的新API

    话不多数,直接上代码: 第一个输出1,2,3,4,5 在函数体中第一个console依次输出1,2,3,4,5 然后再将里面的内容逐个+1,所以第二个输出值为:2,3,4,5,6 但是这都不会改变原数 ...

  10. socket基本用法

    socket介绍 1.什么是socket socket是应用层与传输层中间的一个软件抽象层,它是一组接口.它把TCP/IP这些复杂的协议统一封装起来 这样我们只要知道如何使用socket就好,就已经符 ...