洛谷 P1381 单词背诵

洛谷传送门

题目描述

灵梦有n个单词想要背,但她想通过一篇文章中的一段来记住这些单词。

文章由m个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。

输入格式

第1行一个数n,

接下来n行每行是一个长度不超过10的字符串,表示一个要背的单词。

接着是一个数m,

然后是m行长度不超过10的字符串,每个表示文章中的一个单词。

输出格式

输出文件共2行。第1行为文章中最多包含的要背的单词数,第2行表示在文章中包含最多要背单词的最短的连续段的长度。

输入输出样例

输入 #1复制

输出 #1复制

说明/提示

【数据范围】

对于30%的数据 n<=50,m<=500;

对于60%的数据 n<=300,m<=5000;

对于100%的数据 n<=1000,m<=100000;

题解:

字符串哈希加尺取法枚举区间。

我不会告诉你这俩知识点我都是现学的。

一开始的思路约等于没有思路:挨个枚举,逐字符匹配(憨批),区间枚举。后来发现恶心的要命,根本连打的勇气都没有。

于是字符串哈希上场了。我对哈希的理解就是把一个字符串变成一个数,简化字符串匹配的过程。

关于哈希,如有不会请移步本蒟蒻的总结博客:

浅谈字符串Hash

这样的话,我们把要背的字符串的哈希值存到a数组中,并打上标记。把文章字符串的哈希值存到b数组中。然后核对标记,就可以求出第一问了。

第二问是本题的难点。

如何求出一个最短的符合要求的序列长度呢?

暴力的思路是区间枚举左右端点,核对是否符合条件。但是这样做显然不行,于是我们想到用尺取法优化区间枚举。

关于尺取法,如有不太了解的请移步本蒟蒻的总结博客:

尺取法讲解

了解了尺取法的基本内涵。针对于这道题,我们利用尺取的实现过程是这样的:

因为我们已经求得了第一问的答案,那么我们需要用这个已知答案来确定这个区间是否是可行的解。具体操作方法是:建立一个\(appear[]\)数组,存每个单词(当然是他们的哈希值)出现的次数。如果这个词是第一次出现,那么显然目前区间中的单词数量应该加一。同时,如果这个词出现的次数要是大于等于1的话,那么就尝试进行舍去,看一下有没有更优的选择。

这个地方会比较难理解:我把它叫做”不能偏安一隅“,我们不能只是在\(appear[]\)大于1的时候舍去这个点,等于1的时候一样要舍,为什么呢?就是因为,假如你选择了这个单词作为区间中唯一出现的目标单词,但是它和区间中距离它最近的另一个目标单词非常远,但是区间外面还有一个单词,和距离它最近的目标单词超级近。这个时候你应该选哪一种呢?显而易见,那个更近的对答案的贡献是更优的。所以,我们要在\(appear[]\)等于1的时候也进行舍去,然后继续扫描。因为这个时候的\(ans\)已经被更新了,所以我们不愁答案错误。

然后就求得了第二问的答案。

总的来说,这道题的思路还是比较清晰的,并没有什么太大的难点。主要是尺取法部分的代码实现。以及,提醒大家,数组的大小要开的和模数一样大,否则就会有几率RE...

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=1010;
const int maxm=1e5+10;
const int mod=1e6;
const int p=31;
const int INF=1e9;
int n,m,cnt,ans=INF,l,r;
int a[maxn],b[maxm],appear[mod];
char input[110];
bool need[mod],v[mod];
int hash(char s[])
{
int len=strlen(s);
ll ret=0;
for(int i=0;i<=len;i++)
{
ret*=p,ret+=s[i]-'a';
ret%=mod;
}
return ret%=mod;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",input);
a[i]=hash(input);
need[a[i]]=1;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",input);
b[i]=hash(input);
if(need[b[i]] && !v[b[i]])
cnt++,v[b[i]]=1;
}
if(!cnt)
{
puts("0");
puts("0");
return 0;
}
else
printf("%d\n",cnt);
l=1,r=1;
while(1)
{
if(cnt)
{
if(r>m)
break;
if(need[b[r]])
{
if(!appear[b[r]])
cnt--;
appear[b[r]]++;
}
r++;
}
else
{
while(!need[b[l]])
l++;
if(l>m)
break;
ans=min(ans,r-l);
if(appear[b[l]]==1)
cnt++;
if(appear[b[l]]>=1)
appear[b[l]]--,l++;
}
}
printf("%d",ans);
return 0;
}

洛谷 P1381 单词背诵的更多相关文章

  1. 洛谷 P1381 单词背诵 解题报告

    P1381 单词背诵 题目描述 灵梦有\(n\)个单词想要背,但她想通过一篇文章中的一段来记住这些单词. 文章由\(m\)个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只 ...

  2. 洛谷 - P1381 - 单词背诵 - 哈希 - 尺取

    https://www.luogu.org/problemnew/show/P1381 字符串匹配,用哈希总没有错的. 然后就是尺取了,题目要求首先尽可能多覆盖,那么每次尾巴往后面长. 一开始先找到第 ...

  3. 洛谷 P1101 单词方阵

    题目链接 https://www.luogu.org/problemnew/show/P1101 题目描述 给一n×n的字母方阵,内可能蕴含多个"yizhong"单词.单词在方阵中 ...

  4. 洛谷P1808 单词分类_NOI导刊2011提高(01) 字符串排序

    洛谷P1808 单词分类_NOI导刊2011提高(01) 题目描述 Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类. 两个单词可以分为一类当且 ...

  5. 洛谷 P1019 单词接龙 (DFS)

    题目传送门 当时一看到这题,蒟蒻的我还以为是DP,结果发现标签是搜索-- 这道题的难点在于思路和预处理,真正的搜索实现起来并不难.我们可以用一个贪心的思路,开一个dic数组记录每个单词的最小重复部分, ...

  6. 洛谷——P1101 单词方阵

    https://www.luogu.org/problem/show?pid=1101#sub 题目描述 给一nXn的字母方阵,内可能蕴含多个“yizhong”单词.单词在方阵中是沿着同一方向连续摆放 ...

  7. 洛谷P1101 单词方阵——S.B.S.

    题目描述 给一nXn的字母方阵,内可能蕴含多个“yizhong”单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间[color=red ...

  8. 洛谷P1808 单词分类

    题目描述 Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类. 两个单词可以分为一类当且仅当组成这两个单词的各个字母的数量均相等. 例如“AABA ...

  9. 洛谷 P1019 单词接龙 Label:dfs

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

随机推荐

  1. Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)

    Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul) 1.Eureka Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是 ...

  2. 设计模式-State(行为模式)-很好的实现了对象的状态逻辑与动作实现的分类,状态逻辑在State的派生类实现,动作可以放在Context类中实现。

    以下代码来源: 设计模式精解-GoF 23种设计模式解析附C++实现源码 //Context.h #pragma once class State; class Context { public: C ...

  3. WPF DataGrid 双击行 获得绑定数据

    原文:WPF DataGrid 双击行 获得绑定数据 1)增加事件 2)增加对象获取 1)事件代码 Datagrid 增加事件 MouseDoubleClick="dataGrid_Mous ...

  4. IT兄弟连 Java语法教程 Java语法基础 经典面试题

    1.Java语言中有几种基本类型?分别是什么?请详细说明每种类型的范围以及所占的空间大小? Java语言中有8中基本类型,分别是代表整形的byte.short.int和long,代表浮点型的float ...

  5. Seven Kinds of Testers - 七种类型的测试

    最近读了James大叔的一篇总结Tester类型的文章,获益良多.原文叫做Seven Kinds of Testers(链接:http://www.satisfice.com/blog/archive ...

  6. Java 实现 HtmlEmail 邮件发送功能

    引言 在平常的企业级应用开发过程中,可能会涉及到一些资讯通知需要传达,以及软件使用过程中有一些安全性的东西需要及早知道和了解,这时候在局域网之间就可以通过发送邮件的方式了.以下就是代码实现了: pac ...

  7. 什么是SFP光模块?

    什么是光模块? 光模块(optical module)由光电子器件.功能电路和光接口等组成,光电子器件包括发射和接收两部分.简单的说,光模块的作用就是光电转换,发送端把电信号转换成光信号,通过光纤传送 ...

  8. 【maven】【idea】使用idea的maven进行deploy操作失败,报错:Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project proengine-db-sdk: Failed to deploy artifacts 错误码401

    使用idea的maven进行deploy操作失败,报错: Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:- f ...

  9. Android studio移动项目到另外一个文件夹,结果不能安装的解决方法

    删除.gradle , .idea , build 三个文件夹即可

  10. WPF属性绑定实现双向变化

    WPF依赖项属性可以实现属性的绑定,成功绑定之后只要修改后台绑定的属性,即可UI同步自动更新绑定的值,无需手动刷新界面:同样,前台的值变化后,通过获取绑定的属性值也可获取UI变化后的值,实现双向变化的 ...