文章目录

  • A - ZJM 与霍格沃兹(哈希算法)
    • 题意
    • 输入
    • 输出
    • 样例输入
    • 样例输出
    • 思路
    • 总结
    • 反思
    • 代码
  • B - ZJM 与生日礼物(字典树)
    • 题意
    • 输入
    • 输出
    • 样例输入
    • 样例输出
    • 思路
    • 总结
    • 反思
    • 代码
  • C - ZJM 与纸条(KMP)
    • 题意
    • 输入
    • 输出
    • 样例输入
    • 样例输出
    • 思路
    • 总结
    • 代码

A - ZJM 与霍格沃兹(哈希算法)

题意

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

输入

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

[魔咒] 对应功能

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

输出

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

样例输入

[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

样例输出

light the wand
accio
what?
what?

思路

思路

  • [魔咒] 对应功能 ,求出魔咒哈希值为 Hash1,功能为 Hash2
  • 建立两个 map
    map[Hash1] = index,s1[index] = 功能
    map[Hash2] = index,s2[index] = 魔咒
    题目查询
    根据查询判断是 [魔咒] 还是功能
    然后再在对应的 map 中查询即可
    细节注意:字符串可能出现除 [、] 之外的所有字符

总结

哈希算法讲字符串转成一个数字,用于快速比较查找

反思

  • 注意当hash值很大时,需要取模
  • 这里的魔咒和功能是字符串,其可以包含空格,所以不能用cin读入,用getline

代码

#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<algorithm>
#define mod 1000000007
#define seed 7
using namespace std;
string indstr1[100050],indstr2[100050];
string str1,str2;
map<int,int>mp1,mp2;
int quick_pow(int n,int k,int p)
{int ans=1;while(k){if(k&1) ans=ans*n%p;n=n*n%p;k>>=1;}  return ans;
}
int main()
{    int count=0;string ss;while(getline(cin,ss)){if(ss=="@END@")break;int r=ss.find(']');str1=ss.substr(0,r+1);str2=ss.substr(r+2);//cout<<str1<<endl;cout<<str2<<endl;int hash1=0;for(int i=1;i<str1.size()-1;i++){hash1=hash1+str1[i]*quick_pow(seed,str1.size()-2-(i-1),mod);hash1=hash1%mod;}mp1[hash1]=count;indstr1[count]=str2;int hash2=0;for(int i=0;i<str2.size();i++){hash2=hash2+str2[i]*quick_pow(seed,str2.size()-i,mod);hash2=hash2%mod;}mp2[hash2]=count;indstr2[count]=str1;    count++;}int n;cin>>n;getchar();for(int j=0;j<n;j++){string st;getline(cin,st);if(st[0]=='['){int hash1=0;for(int i=1;i<st.size()-1;i++){hash1=hash1+st[i]*quick_pow(seed,st.size()-2-(i-1),mod);hash1=hash1%mod;}if(mp1.find(hash1)!=mp1.end()){ cout<<indstr1[mp1.find(hash1)->second]<<endl;}else cout<<"what?"<<endl;}else{int hash2=0;for(int i=0;i<st.size();i++){hash2=hash2+st[i]*quick_pow(seed,st.size()-i,mod);hash2=hash2%mod;}  if(mp2.find(hash2)!=mp2.end()){   string s=indstr2[mp2.find(hash2)->second];for(int k=1;k<s.size()-1;k++)cout<<s[k];cout<<endl;//cout<<indstr2[mp2.find(hash2)->second]<<endl;}else cout<<"what?"<<endl;}}return 0;
}

B - ZJM 与生日礼物(字典树)

题意

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

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

输入

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

输出

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

样例输入

01
10
0010
0000
9
01
10
010
0000
9

样例输出

Set 1 is immediately decodable
Set 2 is not immediately decodable

思路

  • 一个字符串和一个字符串集合匹配,因此考虑使用字典树
  • 因为字符串可能有相同的,所以不能全部插入后再判断,所以边插入边判断边记录
  • 往字典树中依次插入每个字符串,假设当前字符串为 S
    有两种情况需要判断
    1)S 是否为之前某个字符串的前缀
    2)之前是否有某个字符串是 S 的前缀
    两种情况判断:
    往字典树中依次插入每个字符串,假设当前字符串为 S
    • S 是否为之前某个字符串的前缀:
      当字符串 S 插入结束后,其最后一个节点是字典树中已经存在的节点,则说明 S 为之前某个字符串的前缀
    • 之前是否有某个字符串是 S 的前缀:
      在字符串 S 插入过程中,如果遇到某一个字典树中的节点为某一个字符串的结尾,则说明存在某个字符串是 S 的前缀

总结

字典树
单个字符串与一堆字符串之间的匹配
例如:集合 T 中有多少个字符串是字符串 S 的前缀
属于简单、好理解的数据结构

反思

代码

字典树模板:

struct Trie
{int tot,root,child[1010][3],flag[1010];Trie(){memset(child,-1,sizeof(child));root=tot=0;}void clear(){memset(child,-1,sizeof(child));memset(flag,0,sizeof(flag));root=tot=0;}bool insert(string str){int now=root;for(int i=0;i<str.size();i++){int x=str[i]-'a';if(child[now][x]==-1){child[now][x]=++tot;flag[now]=0;}now=child[now][x];}flag[now]=1;}//判断是否有完整字符串是str的前缀 bool query(string str){int now=root;for(int i=0;i<str.size();i++){int x=str[i]-'a';if(child[now][x]==-1)return false;if(flag[child[now][x]]) return true;now=child[now][x];/*if(child[now][x]==-1&&flag[now]==0)return false;if(child[now][x]==-1&&flag[now]==1)return true;now=child[now][x];if(flag[now])return true;*/} return false;}
};

题目代码:

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
//int N=1010,charset=3;
struct Trie
{int tot,root,child[1010][3],flag[1010];Trie(){memset(child,-1,sizeof(child));root=tot=0;}void clear(){memset(child,-1,sizeof(child));memset(flag,0,sizeof(flag));root=tot=0;}bool insert(string str){int now=root;bool jud=0;for(int i=0;i<str.size();i++){int x=str[i]-'0';if(child[now][x]==-1){child[now][x]=++tot;flag[now]=0;}else if(i==str.size()-1||flag[child[now][x]])jud=1;now=child[now][x];}flag[now]=1;return jud;}
};
int main()
{string str;Trie t;bool f=0;int count=1;while(cin>>str){if(str=="9"){   t.clear();if(f)cout<<"Set "<<count<<" is not immediately decodable"<<endl;else cout<<"Set "<<count<<" is immediately decodable"<<endl;f=0;count++;continue;}f=max(f,t.insert(str));}return 0;
}

C - ZJM 与纸条(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.

输出

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

样例输入

3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

样例输出

1
3
0

思路

KMP算法

  • 再根据Next数组转移的过程中,如果模式串匹配到的长度等于模式串的长度,则成功匹配。
  • 匹配成功以后根据Next数组进行转移,进行下一轮匹配

总结

KMP
单个字符串与单个字符串的匹配
例如:字符串 S 在字符串 T 中出现的次数

代码

#include<iostream>
#include<string>
using namespace std;
int Next[10010];
string s, p;
void get_Next(string ptr,int len) {Next[0] = 0;for (int i = 1, j = 0; i < len; i++) {while (j && ptr[j] != ptr[i]) j = Next[j - 1];if (ptr[j] == ptr[i]) j++;Next[i] = j;}
}
int KMP(string str, string ptr) {int len1 = str.length();int len2 = ptr.length();int count = 0;int j = 0;//matching ptr[j]get_Next(ptr, len2);for (int i = 0; i < len1; i++) {while (j && ptr[j] != str[i]) j = Next[j - 1];if (ptr[j] == str[i]) j++;if (j == len2) {count++;j = Next[j - 1];}}return count;
}
int main() {int n;cin>>n;while (n--){cin >> p>>s;cout << KMP(s, p) << endl;}
}

week15-作业题--字符串(hash、字典树、KMP)相关推荐

  1. hdu 1800 字符串水题 可用字符串hash 字典树做 我用了最水的排序水过

    具体详解 http://www.cnblogs.com/liqiangqiang/articles/2722116.html 转载于:https://www.cnblogs.com/liqiangqi ...

  2. 字符串处理——字典树

    [概述] 字典树,又称为单词查找树,Tire 树,是一种树形结构,它是哈希树的变种. 字典树与字典很相似,当要查一个单词是不是在字典树中,首先看单词的第一个字母是不是在字典的第一层,如果不在,说明字典 ...

  3. P6688-可重集【字符串hash,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P6688 解题思路 nnn个数,每次有操作 修改一个数 询问两个区间是否他们中的元素分别组成的可重集合A,BA,BA ...

  4. 字典树 —— 字符串分析算法

    这里我们继续来编程训练,在<前端进阶>这个系列里面我们已经讲过一些字符串的算法了.然后这篇文章我们就来一起学习,剩下的几个字符串中比较细节的算法. 字符串分析算法 在开始之前我们先来看看字 ...

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

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

  6. 字典树实现_学习NLP的第3天——字典树

    通过<自然语言处理入门>(何晗)的第2章来学习一下分词的常用算法,因此以下的实现方法都是通过HanLP实现的.这里主要记录我在学习过程中整理的知识.调试的代码和心得理解,以供其他学习的朋友 ...

  7. 分门别类刷leetcode——高级数据结构(字典树,前缀树,trie树,并查集,线段树)

    目录 Trie树(字典树.前缀树)的基础知识 字典树的节点表示 字典树构造的例子 字典树的前序遍历 获取字典树中全部单词 字典树的整体功能 字典树的插入操作 字典树的搜索操作 字典树的前缀查询 字典树 ...

  8. 数据结构之字典树Trie

    文章目录 Trie 字典树 前缀树 什么是Trie 基本概念 基本性质 应用场景 优点 手写一个trie Trie字典树的前缀查询 实现Trie(前缀树) LeetCode208 添加与搜索单词 - ...

  9. php 字典树实现,数据结构之「字典树」

    字典树 字典树,又称 前缀树 或 trie树,是一种有序树,用于保存关联数组,其中的键通常是字符串.与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定.一个节点的所有子孙都有相同的前 ...

  10. 字典树简单实现 插入 查找 遍历

    字典树是一种存储字符串的高效的结构,它保存了不同字符的相同前缀,又因此叫做前缀树,使用前缀,大大避免相同字符的重复匹配,加快查找效率 字典树是一颗多叉树,比如存储26个字母的,那么就有26叉 字典树的 ...

最新文章

  1. 找对业务G点, 体验酸爽 - PostgreSQL内核扩展指南
  2. oracle分区属于什么知识,详细讲解Oracle表分区的相关概念及其优点
  3. UVa 11100 旅行2007
  4. /proc/acpi详细介绍
  5. JS 如何截取部分日期呢
  6. 2018 ios开发者账号同意新协议加联系电话教程
  7. android volley 线程,android第三方框架(一)过时的框架volley
  8. NetworkComms.Net github下载地址
  9. 程序员欢乐送(60):我有一个大胆的想法!
  10. Awesome Blockchain 区块链技术导航
  11. 使用java制作一个个税计算器
  12. pfSense安装和配置pfBlockerNg
  13. 用以太坊区块链和jwt token保证Asp.Net Core的API交互安全(上)
  14. 东莞厚街工业机器人展会_展会效果大起底2020东莞厚街机械展暨2020东莞国际工业自动化及机器人展览会...
  15. C++,软开测开,CV岗面试常考知识点
  16. 【装机吧】Win7电脑系统32位和64位区别(详细版)
  17. FAL:Flash 抽象层的使用
  18. 学习VSC配置opencv
  19. CSS媒体类型基本知识
  20. VirtualBox桥接网络设置无效的解决办法

热门文章

  1. 2015年度APP分类
  2. Word手工双面打印
  3. 天行健,君子自强不息
  4. stm32 jlink Unexceped core id found 0x00000000,excepted 0X3BA00477,MASK 0XFFFFFFFF
  5. matlab LSB算法的三种改进
  6. EGM2008大地水准面模型在工程中的应用综述
  7. swustoj 1132 Coin-collecting by robot
  8. 「精品」无损批量压缩图片工具 - Caesium Image Compressor
  9. 打印预览的时候,总是会多于一个空白页,怎么办?
  10. python简单的构建爬虫ip代理池