目录

  • A.[Hash]咒语
    • 题意
    • 样例
      • 样例输入:
      • 样例输出:
    • 思路
    • 总结
    • 代码
  • B.[字典树]生日礼物
    • 题意
    • 样例
      • 样例输入:
      • 样例输出:
    • 思路
    • 总结
    • 代码
  • C.[kmp]纸条
    • 题意
    • 样例
      • 样例输入:
      • 样例输出:
    • 思路
    • 总结
    • 代码

A.[Hash]咒语

题意

ZJM 为了准备霍格沃兹的期末考试,决心背魔咒词典,一举拿下咒语翻译题
题库格式:[魔咒] 对应功能
背完题库后,ZJM 开始刷题,现共有 N 道题,每道题给出一个字符串,可能是 [魔咒],也可能是对应功能
ZJM 需要识别这个题目给出的是 [魔咒] 还是对应功能,并写出转换的结果,如果在魔咒词典里找不到,输出 “what?”

样例

样例输入:

首先列出魔咒词典中不超过100000条不同的咒语,每条格式为:

[魔咒] 对应功能

其中“魔咒”和“对应功能”分别为长度不超过20和80的字符串,字符串中保证不包含字符“[”和“]”,且“]”和后面的字符串之间有且仅有一个空格。魔咒词典最后一行以“@END@”结束,这一行不属于词典中的词条。
词典之后的一行包含正整数N(<=1000),随后是N个测试用例。每个测试用例占一行,或者给出“[魔咒]”,或者给出“对应功能”。

[expelliarmus] the disarming charm
[rictusempra] send a jet of silver light to hit the enemy
[tarantallegra] control the movement of one's legs
[serpensortia] shoot a snake out of the end of one's wand
[lumos] light the wand
[obliviate] the memory charm
[expecto patronum] send a Patronus to the dementors
[accio] the summoning charm
@END@
4
[lumos]
the summoning charm
[arha]
take me to the sky

样例输出:

每个测试用例的输出占一行,输出魔咒对应的功能,或者功能对应的魔咒。如果在词典中查不到,就输出“what?”

light the wand
accio
what?
what?

思路

1.字符串哈希 用两个map进行映射
map[Hash1] = index,s1[index] = 翻译
map[Hash2] = index,s2[index] = 英文
2.对于输入的每一次查询 首先判断是咒语还是翻译
然后再在对应的 map 中查询即可
PS:因为可能出现其他字符 故要注意减 ’ ’ 而不是减’a’ 因为用到了unsigned long long 自然溢出 故加的值不能为负值


总结

一个经典的字符串哈希问题,可以让我们很好的打下哈希算法的基础
seed:通常取7、17、131
mod:1e9+7 或 unsigned long long自然溢出
可以在O(1)时间内修改,合并


代码

#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<map>
#define MAXN 100010
#define seed 131
#define ull unsigned long long
using namespace std;
char mz[MAXN][30],fy[MAXN][90];
int tnt,n;
map<ull,int> M,F;
ull Hash(char *str)
{ull sum=0,sed=1;for(int i=strlen(str);i>=0;i--){sed*=seed;sum+=(str[i]-' ')*sed;   }return sum;
}
char q[110];
int main()
{string s1,s2;while(true){cin>>s1;if(s1.compare("@END@")==0)  break;tnt++;getline(cin,s2);strcpy(mz[tnt],s1.c_str());strcpy(fy[tnt],s2.c_str()+1);M[Hash(mz[tnt])]=tnt;F[Hash(fy[tnt])]=tnt;}cin>>n;getchar();string s3;for(int i=1;i<=n;i++){getline(cin,s3);strcpy(q,s3.c_str());ull has=Hash(q);if(q[0]=='[')//咒语{if(M.find(has)==M.end())    cout<<"what?"<<endl;else cout<<fy[M[has]]<<endl;}else{if(F.find(has)==F.end())    cout<<"what?"<<endl;else {for(int i=1;i<strlen(mz[F[has]])-1;i++)cout<<mz[F[has]][i];cout<<endl;}}}return 0;
}

B.[字典树]生日礼物

题意

ZJM 收到了 Q老师 送来的生日礼物,但是被 Q老师 加密了。只有 ZJM 能够回答对 Q老师 的问题,Q老师 才会把密码告诉 ZJM。

Q老师 给了 ZJM 一些仅有 01 组成的二进制编码串, 他问 ZJM:是否存在一个串是另一个串的前缀.

样例

样例输入:

多组数据。每组数据中包含多个仅有01组成的字符串,以一个9作为该组数据结束的标志。

01
10
0010
0000
9
01
10
010
0000
9

样例输出:

对于第 k 组数据(从1开始标号),如果不存在一个字符串使另一个的前缀,输出"Set k is immediately decodable",否则输出"Set k is not immediately decodable"。
每组数据的输出单独一行

Set 1 is immediately decodable
Set 2 is not immediately decodable

思路

1.由于是单个字符串与一堆字符串之间的匹配,我们首先想到字典树

2.如何判断是否存在一个字符串是其他某个字符串的子串?
我们要考虑两方面,
一是,某字符串是否是其他字符串的前缀?
二是,其他字符串中是否存在某一字符串,是该字符串的前缀?

3.故对于每一字符串,我们可以边插入到字符串中,边判断即可


总结

我们通常用一个结构体来存储字典树
基本函数有clear(),insert(),query()(查询字典树中是否有某字符串的前缀)


代码

#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<map>
using namespace std;
struct Trie
{//N为字典树的最多节点个数 charset为字符的种类数 本题中只有0和1static const int N=100010,charset=2;//child[now][x] 表示now的第x个儿子 //flag[now]=1表示now是某一字符串的结尾int tnt,root,child[N][charset],flag[N];Trie() {memset(child,-1,sizeof(child));memset(flag,0,sizeof(flag));root=tnt=0;}void clear(){memset(child,-1,sizeof(child));memset(flag,0,sizeof(flag));root=tnt=0;}/*void insert(char *str){//原版insertint now=root;for(int i=0;i<strlen(str);i++){int x=str-'0';//if(child[now][x]==-1)//如果还没有创建该节点{child[now][x]=++tnt;//创建新节点flag[now]=0;}now=child[now][x];}flag[now]=1;//标识结尾}*/int insert(char *str){int now=root,len=strlen(str),ok=0;for(int i=0;i<len;i++){int x=str[i]-'0';if(child[now][x]==-1){child[now][x]=++tnt;flag[now]=0;}else if(i==len-1||flag[child[now][x]])  ok=1;//i==len-1 表示 当前子串是之前曾经插入过的字符串的子串//flag[child[now][x]] 表示 之前的字符串是当前插入的字符串的子串now=child[now][x];}flag[now]=1;return ok;}bool query(char * str){int now=root;for(int i=0;i<strlen(str);i++){int x=str[i]-'0';if(child[now][x]==-1)   return false;//还没有找到尾就到头了if(flag[now])   return true;//已经找到了一个字符子串now=child[now][x];}return false;//到头了还是没找到一个子串}
};
int T;
char c[1010];
int main()
{Trie t;string s;bool ans=false;while(cin>>s){if(s.compare("9")==0)   {T++;if(!ans) cout<<"Set "<<T<<" is immediately decodable"<<endl;else cout<<"Set "<<T<<" is not immediately decodable"<<endl;t.clear();ans=false;continue;}strcpy(c,s.c_str());if(t.insert(c)) ans=true;}system("pause");return 0;
}

C.[kmp]纸条

题意

ZJM 的女朋友是一个书法家,喜欢写一些好看的英文书法。有一天 ZJM 拿到了她写的纸条,纸条上的字暗示了 ZJM 的女朋友 想给 ZJM 送生日礼物。ZJM 想知道自己收到的礼物是不是就是她送的,于是想看看自己收到的礼物在纸条中出现了多少次。

样例

样例输入:

第一行输入一个整数代表数据的组数

每组数据第一行一个字符串 P 代表 ZJM 想要的礼物, 包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 并且字符串长度满足 1 ≤ |P| ≤ 10,000 (|P| 代表字符串 P 的长度).
接下来一行一个字符串 S 代表 ZJM 女朋友的纸条, 也包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 满足 |P| ≤ |S| ≤ 1,000,000.

3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

样例输出:

输出一行 一个整数代表 P 在 S中出现的次数.

1
3
0

思路

1.由于本题为单个字符串与单个字符串匹配,是典型的查询S在T中出现的次数的问题,故可以用KMP算法在O(m+n)内实现

2.KMP的模板题,只需在匹配到时将ans++即可

KMP有两部分难点
一是Next[]数组的快速求解
二是KMP算法中的匹配过程
详情可见:KMP算法详细讲解


总结


代码

#include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<map>
using namespace std;
int n,ans;
int Next[1000010];
string P,S;
void get_next()
{Next[0]=0;for(int i=1,j=0;i<P.length();i++){while(j&&P[j]!=P[i])    j=Next[j-1];if(P[j]==P[i])  j++;Next[i]=j;}
}
void kmp()
{int len2=S.length();int j=0;//当前匹配到了P的第几个字符get_next();for(int i=0;i<len2;i++){//只有当j!=0时 向前寻找才有意义while(j&&P[j]!=S[i]) j=Next[j-1];if(P[j]==S[i])  j++;if(j==P.length())//匹配到了一次{ans++;j=Next[j-1];}}
}
int main()
{cin>>n;while(n--){memset(Next,0,sizeof(Next));ans=0;cin>>P>>S;kmp();cout<<ans<<endl;}return 0;
}

[哈希/字典树/kmp]Exercise Week15 A~C相关推荐

  1. 【Hihocoder - offer编程练习赛39 - D】前缀后缀查询(后缀字典树,哈希,思维)

    题干: 时间限制:10000ms 单点时限:1000ms 内存限制:512MB 描述 给定一个包含N个单词的字典:{W1, W2, W3, ... WN},其中第i个单词Wi有具有一个权值Vi. 现在 ...

  2. 012-数据结构-树形结构-哈希树[hashtree]、字典树[trietree]、后缀树

    一.哈希树概述 1.1..其他树背景 二叉排序树,平衡二叉树,红黑树等二叉排序树.在大数据量时树高很深,我们不断向下找寻值时会比较很多次.二叉排序树自身是有顺序结构的,每个结点除最小结点和最大结点外都 ...

  3. 2020.9.9华为笔试记忆:KMP+记忆化搜索+字典树

    2020.9.9华为笔试 当然,出现在我博客中的笔试都不是我自己的笔试(人家也不给我发笔试链接,小声bibi,诶,好像我也没投,hhhahahha 记者:为什么要做笔试? 我:生活无聊了喏,肯定要做啊 ...

  4. 基础数据结构(二):字典树、并查集、堆、哈希表、字符串的哈希方式、STL的常见容器及其接口

    文章目录 一.字典树Trie 1 原理 2 Trie字符串统计 3 [LeetCode 208. 实现 Trie (前缀树)](https://leetcode-cn.com/problems/imp ...

  5. [leetcode 面试题 17.17] -- 多次搜索,KMP与字典树

    [leetcode 面试题 17.17] -- 多次搜索 题目来源 分析 KMP思路 完整代码 字典树 完整代码 题目来源 https://leetcode-cn.com/problems/multi ...

  6. LeetCode第 57 场力扣夜喵双周赛(差分数组、单调栈) and 第 251 场力扣周赛(状态压缩动规,树的序列化,树哈希,字典树)

    LeetCode第 57 场力扣夜喵双周赛 离knight勋章越来越近,不过水平没有丝毫涨进 1941. 检查是否所有字符出现次数相同 题目描述 给你一个字符串 s ,如果 s 是一个 好 字符串,请 ...

  7. [week15] B - ZJM与生日礼物(选做)—— 字典树

    文章目录 题意 Input Output 输入样例 输出样例 提示 分析 总结 代码 题意 ZJM 收到了 Q老师 送来的生日礼物,但是被 Q老师 加密了.只有 ZJM 能够回答对 Q老师 的问题,Q ...

  8. 【Week15作业 B】ZJM与生日礼物【字典树】

    题意: ZJM 收到了 Q老师 送来的生日礼物,但是被 Q老师 加密了.只有 ZJM 能够回答对 Q老师 的问题,Q老师 才会把密码告诉 ZJM. Q老师 给了 ZJM 一些仅有 01 组成的二进制编 ...

  9. Week15—字典树应用,字符串包含问题

    问题描述 ZJM 收到了 Q老师 送来的生日礼物,但是被 Q老师 加密了.只有 ZJM 能够回答对 Q老师 的问题,Q老师 才会把密码告诉 ZJM. Q老师 给了 ZJM 一些仅有 01 组成的二进制 ...

  10. 0x16.基本数据结构 — Trie树(字典树)+ A C 自 动 机

    目录 用TrieTrieTrie树来处理整数异或问题是真的舒服! 一.TrieTrieTrie树 TrieTrieTrie的基本操作 0.初始化 1.插入 2.检索 二.TrieTrieTrie树例题 ...

最新文章

  1. Elastic-Job中的ScriptJob
  2. 【分享】虹软人脸识别应用开发过程
  3. Spring Boot 与消息 (JMS、AMQP、RabbitMQ)
  4. IOC操作Bean管理XML方式(FactoryBean)
  5. mac下安装caffe
  6. my footprint :走过的路
  7. Android中样式及主题
  8. android input 点击事件失效,React Native:TextInput元素上的onContentSizeChange事件在Android上不起作用...
  9. 一种新的人机交流方式——sound ware 声件
  10. Git:git commit后撤销commit 提交
  11. 软媒时间---任务栏滚动工具
  12. 百科不全书之Python常用库
  13. 一文聊透对象在JVM中的内存布局,以及内存对齐和压缩指针的原理及应用
  14. Couldnt check the working tree for unmerged files because of an error. bad signature index file cor
  15. 数据校验(身份证,ip地址,银行卡号等)
  16. 程序猿最后的愿望是什么?
  17. WinForm,可能是Windows上手最快的图形框架了
  18. php 微信永久登录,php微信登录
  19. IPv4协议中的UDP分片问题
  20. 小路绫只会做料理 (ayaya)(树状数组 二分)

热门文章

  1. 实用开源镜像站(将持续补全......)
  2. wps压缩word文档方法
  3. 利用Python进行数据分析的学习笔记——chap12
  4. scrapy 使用无忧代理IP 需要填写无忧代理IP提供的API订单号(请到用户中心获取) 这个是要钱吗??...
  5. matlab 中输入log就是ln吗?(ln就是log以e为底的对数)
  6. (OK) 国内常用NTP服务器地址及IP
  7. 破解docx文档保护密码
  8. DS18B20数字温度计 (二) 测温, ROM和CRC算法
  9. 未来是否繁花似锦,源自我们当下之努力
  10. 2020年中国不支持苹果_苹果2020年9月事件提示