洛谷 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. 用VB脚本复制文件夹并跳过重复文件

    VB中可通过 scripting.filesystemobject 对象操作文件,其中复制文件或文件夹的函数参数可选覆盖或不覆盖.选择覆盖时,如果目标路径存在同名文件或文件夹,则替换掉已存在的文件.而 ...

  2. ssm-restful风格

    码云 https://gitee.com/MarkPolaris/ssm-test02

  3. ASP.NET Core 模型验证的一个小小坑

    今天在我们的一个项目中遇到一个 asp.net core 模型验证(model validation)的小问题.当模型属性的类型是 bool ,而提交上来的该属性值是 null ,asp.net co ...

  4. Linux 部署 nginx

    nginx搭建 1. 清除之前nginx环境 #查看nginx进程 ps -ef|grep nginx #找到nginx相对应的位置 whereis nginx #停止nginx服务 /usr/loc ...

  5. centos7之firewalld防火墙的配置与使用

    firewalld是centos7开始提供的管理防火墙工具,提供了一个动态管理的防火墙,当然低层仍然调用的是 netfilter . 一.区域(zone)firewalld将网卡对应到不同的区域(zo ...

  6. solidity 智能合约之间的调用

    智能合约之间的调用 在区块链上,有些功能往往无法通过一个智能合约完成,此时便会用到智能合约之间的调用.本篇文章带大家通过具体示例来了解一下智能合约之间的调用. 在智能合约的编译过程中,有两种情况:调用 ...

  7. C# - 操作Word文档小实验

    前言 本篇主要记录:VS2019 WinFrm桌面应用程序实现对Word文档的简单操作. 准备工作 搭建WinFrm前台界面 添加必要的控件,如下图 NuGet包管理器 安装Microsoft.Off ...

  8. asp.net core 新建area使用asp-action,asp-controller不管用

    解决方法: 在新建的Area目录下,这里使用Admin,Admin/Views下新建_ViewImports.cshtml和_ViewStart.cshtml两个视图文件,复制项目自动生成的到对应的新 ...

  9. Javase之集合泛型

    集合泛型知识 泛型 是一种把类型明确工作推迟到创建对象或者调用方法的时候才明确的特殊类型. 也称参数化类型,把类型当成参数传递. 在jdk1.5中出现.一般来说经常在集合中使用. 格式 <数据类 ...

  10. Sublime Text 3 插件安装、搭建Python、Java开发环境

    一.下载并安装 Sublime Text 3 官网地址:http://www.sublimetext.com目前最新版本为:3.2.1 (BUILD 3207)安装时勾选“Add to explore ...