单词检索(search)

\(Description\)

小可可是学校图书馆的管理员,现在他接手了一个十分棘手的任务。

由于学校需要一些材料,校长需要在文章中检索一些信息。校长一共给了小可可N篇文章,每篇文章为一个字符串。现在,校长需要他找到这样的单词,它至少在这N篇文章中的M篇文章里出现过,且单词长度为L。可是,工作量十分庞大,但校长又急需小可可完成这项任务。

现在他向你求助,需要你编写程序完成这项艰巨的任务。

\(Input\)

第1行3个正整数N,M,L,表示文章的数目,单词至少出现在M篇文章中和每个单词的长度。

接下来N行,每行一个字符串,表示一篇文章。

\(Output\)

仅一行,表示满足检索条件的单词数。

\(Sample Input\)

3 2 2

noip

istudycpp

imacppstudent

\(Sample Output\)

5

【样例解释】

这5个单词分别为:st,tu,ud,pp,cp。

\(Data Constraint\)

对于20%的数据有1≤N,M≤10;

对于60%的数据有1≤N,M≤100;

对于100%的数据有1≤N,M≤2000,L≤1000。每篇文章长度不大于1000,均有小写字母组成。

思路

字符串?

既然限定了答案字符的长度,那很容易想到分离字符串,统计出现个数

那就是 \(O(nl)\) 级别的个数,空间可以承受

然后怎么存分离出的字符

如果可以

对于每一篇文章,我们把分离的字符去重(因为答案要求的字符至少在N篇文章中的M篇文章里出现过)

最后合在一起

此时统计出现次数超过 \(M\) 的字符数量就是答案

想想,没有问题

关键是分离

如果把每个字符截取下来,那么一片文章处理的复杂度就是 \(O(|S|l)\)

\(n\) 篇就是 \(O(n|S|l)\) 的,显然不可以承受

然后呢?

正解

既然有了思路,那就直接打吧(也有 \(60\) 分了)

可是,现在是追求正解的时候

思路中的瓶颈在于分离字符

而我们知道要获取一段区间的信息,如果满足可加性,那就可以前缀和维护

字符串?

哦,哈希!

具体方式

对于一个字符串,我们对其进行哈希时,考虑映射成一个数字

一个很巧妙的方法是:把字符本身当做一串数字,一个字符对应权值

从高到低每一位的位权就参考十进制的方法,记作 \(B^{k-1}\)

其中 \(k\) 为第 \(k\) 位,\(B\) 是几进制

因为题中字符串均由小写字母构成

所以设为 \(26\) 进制(不这样也行,哈希映射的方法自己选择)

那么对于一个字符串S,有:

\[H(S) = \sum_{i=1}^{|S|} c_iB^{|S|-i}
\]

截取 S 中后 \(l\) 个字符组成的字符串设为 C',前 \(|S| - l\) 个字符组成的字符串设为 C

\[H(C') = H(S) - H(C) * B^l
\]

于是维护 \(s_i =\sum_{k=1}^i H(|1...k|)\)

双模数,以防万一

代码

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL p1 = 1e9 + 7 , p2 = 1e9 + 9 , B = 26;
LL s1[1005] , s2[1005] , b1[1005] , b2[1005];
struct node{
LL x , y;
}d[2000005] , c[2000005];
int cnt , tot , n , m , l , ans;
char ch; inline bool cmp(node a , node b){return (a.x < b.x || (a.x == b.x && a.y < b.y));} int main()
{
scanf("%d%d%d" , &n , &m , &l);
b1[0] = b2[0] = 1;
for(register int i = 1; i <= 1001; i++) b1[i] = b1[i - 1] * B % p1;
for(register int i = 1; i <= 1001; i++) b2[i] = b2[i - 1] * B % p2;
int x;
for(register int i = 1; i <= n; i++)
{
x = 0 , s1[0] = 0 , s2[0] = 0 , cnt = 0;
ch = getchar();
while (ch < 'a' || ch > 'z') ch = getchar();
for(; ch >= 'a' && ch <= 'z'; ch = getchar())
{
x++;
s1[x] = (s1[x - 1] * B % p1 + (ch - 'a' + 1)) % p1;
s2[x] = (s2[x - 1] * B % p2 + (ch - 'a' + 1)) % p2;
if (x >= l)
{
d[++cnt].x = (s1[x] + p1 - s1[x - l] * b1[l] % p1) % p1;
d[cnt].y = (s2[x] + p2 - s2[x - l] * b2[l] % p2) % p2;
}
}
sort(d + 1 , d + cnt + 1 , cmp);
c[++tot] = d[1];
for(register int j = 2; j <= cnt; j++)
if (d[j].x != d[j - 1].x || d[j].y != d[j - 1].y)
c[++tot] = d[j];
}
sort(c + 1 , c + tot + 1 , cmp);
x = 1;
while (x <= tot)
{
int s = 1;
while (c[x].x == c[x + 1].x && c[x].y == c[x + 1].y && x < tot) x++ , s++;
if (s >= m) ans++;
x++;
}
printf("%d" , ans);
}

单词检索(search)的更多相关文章

  1. 英语单词小程序插件 - EdictPlugin-LTS

    1.插件引入 全局app.json配置 "plugins": { "edict-plugin": { "version": "1. ...

  2. 通过trie树实现单词自动补全

    /** * 实现单词补全功能 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #incl ...

  3. 从Search Sort到Join

    发表于<程序员>2015年4月B的一篇文章,在博客归档下.根据杂志社要求,在自己博客发表该文章亦须注明:本文为CSDN编译整理,未经允许不得转载,如需转载请联系market#csdn.ne ...

  4. 告别炼丹,Google Brain提出强化学习助力Neural Architecture Search | ICLR2017

    论文为Google Brain在16年推出的使用强化学习的Neural Architecture Search方法,该方法能够针对数据集搜索构建特定的网络,但需要800卡训练一个月时间.虽然论文的思路 ...

  5. 海量数据处理之Tire树(字典树)

    参考博文:http://blog.csdn.net/v_july_v/article/details/6897097 第一部分.Trie树 1.1.什么是Trie树 Trie树,即字典树,又称单词查找 ...

  6. 搜索系统核心技术概述【1.5w字长文】

    前排提示:本文为综述性文章,梳理搜索相关技术,如寻求前沿应用可简读或略过 搜索引擎介绍 搜索引擎(Search Engine),狭义来讲是基于软件技术开发的互联网数据查询系统,用户通过搜索引擎查询所需 ...

  7. 关于 微软必应词典客户端(pc) 的案例分析

    第一部分 调研,评测 ●评测 bug one 在词典界面中搜完单词后,将鼠标移到英文例句上的单词时,会显示对应的中文翻译,而当移到短语时则不对应中文翻译. bug two 用orc强力取词,查询如上图 ...

  8. ***PHP preg_match正则表达式的使用

    第一,让我们看看两个特别的字符:‘^’和‘$’他们是分别用来匹配字符串的开始和结束,以下分别举例说明 : "^The": 匹配以 "The"开头的字符串; &q ...

  9. Trie树也称字典树

    Trie树 Trie树也称字典树,因为其效率很高,所以在在字符串查找.前缀匹配等中应用很广泛,其高效率是以空间为代价的. 一.Trie树的原理 利用串构建一个字典树,这个字典树保存了串的公共前缀信息, ...

  10. 第四次作业——WORDSEARCH小游戏

    “谁想出来的这么缺德的题目啊!!!!”一个声音在我心中回荡 这个题目很早就在课堂上公布了,我和我的小伙伴都惊呆了! 这是个毛?根本无从下手的感觉 总是觉得这个小游戏不是程序能给出答案的,因为我的第一印 ...

随机推荐

  1. python实现图片转换pdf

    安装第三方库 linux平台 sudo apt install python3-reportlab python3-pil 示例代码 import sys from reportlab.pdfgen ...

  2. Oracle 一对多将多行数据整理为一行

    在开发中一对多的关系经常用到,昨天遇到一个客户问题,要求将所有反馈任务的信息整理为一行展示并导出excel. 我数据库对应关系:通任务task对应feedback表多个反馈,也就是说每个任务都有很多条 ...

  3. 【笔面试真题】ThoughtWorks-笔试-2022年1月21日

    一.选择填空判断 2n-1 二.算法题 算法题1:配对括号 算法题2:计算有效票数? 算法题3:求字符串中指定单词的数量 package com.jhliu20.real; import java.u ...

  4. ORM增删改查 django请求生命周期图 django路由层及反向解析

    目录 可视化界面之数据增删改查 1.建表 2.数据展示功能 3.数据添加功能 4.数据编辑功能 5.数据删除功能 django请求生命周期流程图 django路由层 1.路由匹配 2.转换器功能 pa ...

  5. python Flask 操作数据库(2)

    单表操作 数据准备 from flask import Flask from flask_sqlalchemy import SQLAlchemy class Config: DEBUG = True ...

  6. ClickHouse ORM 3.x 发布啦

    经过1年断断续续的迭代,ClickHouse ORM 3.x 发布啦-说说它的故事吧. 回顾下2022 说来惭愧上次写博客都是22年4月份了,今年行情不好团队急剧收缩,工作几乎全扑在接手存量业务和主业 ...

  7. [数据结构]Dijkstra算法求单源最短路径

    概念 求带权有向图中某个源点到其余各个顶点的最短路径,最常用的是Dijkstra算法.该算法设置一个集合S记录已求得的最短路径的顶点,可用一个数组s[]来实现,初始化为0,当s[Vi]=1时表示将顶点 ...

  8. 一次JVM GC长暂停的排查过程

    作者:京东科技 徐传乐 背景 在高并发下,Java程序的GC问题属于很典型的一类问题,带来的影响往往会被进一步放大.不管是「GC频率过快」还是「GC耗时太长」,由于GC期间都存在Stop The Wo ...

  9. 题解P1559 运动员最佳匹配问题

    简要题意 给出 \(n\) 个白色顶点,\(n\) 个黑色顶点.白色顶点 \(i\) 和黑色顶点 \(j\) 之间的边的权为 \(P_{i,j}\cdot Q_{j,i}\),求二分图最大权匹配. 思 ...

  10. C# 如何发送邮件消息

    1.安装NUGET包 MailKit 2.代码如下 using MailKit.Net.Smtp; using MimeKit; using System.Collections.Generic; u ...