题目描述

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

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

输入输出格式

输入格式:

第1行一个数n,

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

接着是一个数m,

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

输出格式:

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

输入输出样例

输入样例#1:

3
hot
dog
milk
5
hot
dog
dog
milk
hot

输出样例#1:

3
3

说明

【数据范围】

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

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

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

题解:

本题真是显示出了pb_ds库功能的强大。不懂这个库的可看一下这篇文章:

http://www.cnblogs.com/huihao/p/7137250.html

思路一:

先解决第一问:用两个哈希表一个记录必背单词,一个记录这个但是是否被背过。

第二问我们发现最多要背单词的最短的连续段的长度满足单调性,我们就可以用一个队列来实现,在队列中记录。注意数据中有一个点要特判,因为最多包含的要背的单词数是0,循环会死在里面的。

我首先想到的使用STL库中的set写,因为要保证每个单词的唯一性。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<set>
using namespace std;
using namespace __gnu_pbds;
gp_hash_table<string,bool>h1;
gp_hash_table<string,bool>h2;
gp_hash_table<string,int>h3;
int n,m,num;
char s[101001][20];
set<string> a;
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s[i]);h1[s[i]]=1;}scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%s",s[i]);if(h1[s[i]]&&!h2[s[i]]){num++;h2[s[i]]=1;}}int l=1,minn=100000000;for(int i=1;i<=m;i++){if(h1[s[i]]){a.insert(s[i]);h3[s[i]]++;}int tmp=a.size();while(tmp==num){minn=min(minn,i-l+1);if(h1[s[i]]){h3[s[l]]--;if(h3[s[l]]==0) {a.erase(s[l]);tmp--;}}l++;}}printf("%d\n%d\n",num,minn);return 0;
}

思路二;

但后来发现完全没这个必要,因为set的效率有点低,如果不断地插入删除,数据小的话有可能过,数据大的话就卡死了。所以我们可以在开个哈希表记录每个必背单词在队列从中出现的次数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
cc_hash_table<string,bool>h1;
cc_hash_table<string,bool>h2;
cc_hash_table<string,int>h3;
int n,m,num;
char s[120001][20];
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s[i]);h1[s[i]]=1;}scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%s",s[i]);if(h1[s[i]]&&!h2[s[i]]){num++;h2[s[i]]=1;}}int l=1,minn=100000000;int cnt=0;for(int i=1;i<=m;i++){if(h1[s[i]]){if(!h3[s[i]])cnt++;h3[s[i]]++;}while(cnt==num){if(l==i) {minn=0;break;}minn=min(minn,i-l+1);if(h1[s[l]]){h3[s[l]]--;if(h3[s[l]]==0) cnt--;}l++;}}printf("%d\n%d\n",num,minn);return 0;
}

思路三:

哈希+二分,经过优化之后貌似快了一些。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,e,wo;
char x[13];
int b[10003];
unsigned long long y[100005];
unsigned long long q[15];
unsigned long long g[1006],t[100005];
inline unsigned long long has(char ss[13])
{unsigned long long tot=0;for(int i=strlen(ss)-1;i>=0;i--){tot+=(ss[i]-'a'+1)*q[i];}return tot;
}
bool ef(int l,int r,unsigned long long k)
{e=(l+r)>>1;if(k==t[e]) return 1;if(l==r) return 0;if(k<t[e]) return ef(l,e,k);else return ef(e+1,r,k);
}
int ff(int l,int r,unsigned long long k)
{e=(l+r)>>1;if(k==g[e]) return e;if(l==r) return 0;if(k<g[e]) return ff(l,e,k);else return ff(e+1,r,k);
}
void init()
{q[1]=1;for(int i=2;i<=13;i++)q[i]=q[i-1]*27;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",&x);g[i]=has(x);}scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%s",&x);t[i]=has(x);y[i]=t[i];}
}
int main()
{int tot=0,z;init();sort(t,t+m+1);for(int i=1;i<=n;i++) if(ef(1,m,g[i])) tot++;printf("%d\n",tot);wo=tot;int l=0,r=0;int mi=m;sort(g,g+n+1);if(tot==0) mi=0;elsewhile(1){if(wo==0){if(mi>r-l) mi=r-l;l++;z=ff(1,n,y[l]);if(z!=0) {b[z]--;if(b[z]==0) wo++;}}else {if(r==m) break;r++;z=ff(1,n,y[r]);if(z!=0) {b[z]++;if(b[z]==1) wo--;}}}printf("%d\n",mi);return 0;
}

转载于:https://www.cnblogs.com/huihao/p/7128694.html

【洛谷P1381】单词背诵相关推荐

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

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

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

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

  3. 洛谷P1019 单词接龙

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

  4. 【搜索】NOIP2000 or 洛谷1019单词接龙

    题目链接:洛谷1019 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的"龙"(每个单词都最多在 ...

  5. 洛谷P1101 单词方阵 (C语言 + 详细注释 + 五妙)

    //首先声明一下,我的代码大部分是参照洛谷的一位博客:Way_How_Fri3nd.看完后我就觉得写的非常好,由于我不知道怎么转载洛谷的博客,所以干脆自己写一篇CSDN博客,因为写的实在是太好了,我迫 ...

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

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

  7. 洛谷——P1101 单词方阵

    题目描述 给一n \times nn×n的字母方阵,内可能蕴含多个"yizhong"单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着 88 个方向的任一方向,同一单词摆放时不 ...

  8. 洛谷——P1019 单词接龙

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

  9. 洛谷 P1019 单词接龙

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

最新文章

  1. java中mymaps_Java MyLocationStyle.myLocationType方法代码示例
  2. java 注解_怎样理解 Java 注解和运用注解编程?
  3. 解决C/C++语言中全局变量重复定义的问题
  4. 一次线上Redis类转换异常排查引发的思考
  5. 算法竞赛入门经典(第二版) | 程序3-6 WERTYU (UVa 10082)(常量数组)
  6. Zabbix linux agent 安装
  7. Python入门基础篇(一)列表,详细实用,简单易懂!!!!
  8. 解决微信小程序使用switchTab跳转后页面不刷新的问题
  9. 中澳科学家在量子安全通信领域合作研究取得突破性进展
  10. 生信技能树课程记录笔记(二)20220523-20220524
  11. SVN客户端下载及安装
  12. IT项目管理流程以及每个步骤用到的文档
  13. 联想摄像头无法一直运行
  14. Java 基础知识总结—String 类
  15. 西游降魔之东去的西游
  16. 霍夫变换c语言程序,霍夫变换 | Cauthy's Blog
  17. openmv 神经网络 超出内存_星瞳科技OpenMV视频教程22-神经网络cifar_10
  18. 抖音是怎么动摇美国国本的?
  19. 面向对象程序设计c++版董正言张聪课本课后习题答案第二章
  20. riak mysql_Riak安装

热门文章

  1. 14.索引数组初始化
  2. Hibernate【XXXX.hbm.xml】总结
  3. 中外教育专家“支招”中国学生如何接轨国际教育
  4. 11月12日云栖精选夜读 | 2135亿!新技术的力量刚刚开始
  5. kotlin 类及其成员的可见性
  6. 谈mvc开发中gzip压缩的应用
  7. 面向对象的编程学习笔记
  8. CodeForces 660B Seating On Bus
  9. pku3661 Running
  10. XML与DataSet的相互转换