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

题干:

时间限制:10000ms

单点时限:1000ms

内存限制:512MB

描述

给定一个包含N个单词的字典:{W1, W2, W3, ... WN},其中第i个单词Wi有具有一个权值Vi。  

现在小Hi要进行M次查询,每次查询包含一个前缀字符串Pi和一个后缀字符串Si。他希望知道同时以Pi为前缀并且以Si为后缀的单词中,权值最大的单词的权值是多少?

假设字典包含"hihocoder"、"hijacker"和"hiker",权值依次是30、20和10。  

那么对于查询前缀="hi",后缀="er",答案应为30.

输入

第一行包两个整数N和M。(1 <= N <= M)  

以下N行每行包含一个只包含小写字母的字符串Wi和对应的权值Vi。  

再之后M行每行包含两个字符串Pi和Si。

对于30%的数据,1 <= N, M <= 100  

对于100%的数据,1 <= N, M <= 50000, 1 <= |Wi|, |Pi|, |Si| <= 10, 1 <= Vi <= 100000

输出

输出最大的权值。如果没有符合条件的单词,输出-1。

样例输入

3 2  
hihocoder 30  
hijacker 20  
hiker 10  
hi er  
hihoco hocoder

样例输出

30  
30

解题报告:

    查询有前缀和后缀的条件,考虑固定其中一个条件;单词长度很短,在每个单词的每个前缀下再建一颗后缀字典树,在后缀字典树下维护权值。查询时,先匹配前缀,再查询后缀。

   这题还有第二种方法,字典树哈希,先建同一棵字典树然后按照每个点的root当做seed去哈希,前缀与后缀用一个模数分开(这里取的1000007)map去哈希同时维护最大权值

AC代码1:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<unordered_map> 
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e6 + 5;
char s[55];
int trie[MAX][33];
int val[MAX];
int tot;
void insert(char str[],int w) {int rt = 0,tmprt,len = strlen(str);for(int i = 0; i<len; i++) {int cur = str[i] - 'a';if(!trie[rt][cur]) trie[rt][cur] = ++tot;rt = trie[rt][cur];//接下来建立后缀字典树if(!trie[rt][27]) trie[rt][27] = ++tot;tmprt = trie[rt][27];for(int j = len-1; j>=0; j--) {int cur = str[j] - 'a';if(!trie[tmprt][cur]) trie[tmprt][cur] = ++tot; tmprt = trie[tmprt][cur];val[tmprt] =max(val[tmprt],w);}}
}
int ask(char str[],char qq[]) {int res = 0,len = strlen(str),rt = 0;for(int i = 0; i<len; i++) {int cur = str[i] - 'a';if(trie[rt][cur] == 0) return -1;else rt = trie[rt][cur];}if(trie[rt][27] == 0) return -1;rt = trie[rt][27];len = strlen(qq);for(int i = 0; i<len; i++) {int cur = qq[i] - 'a';if(trie[rt][cur] == 0 ) return -1;else rt = trie[rt][cur];}return val[rt];
}
int main()
{int n,m;cin>>n>>m;for(int w,i = 1; i<=n; i++) {scanf("%s%d",s,&w);insert(s,w);}char a[55],b[55];while(m--) {scanf("%s%s",a,b);int lenb = strlen(b);reverse(b,b+lenb);printf("%d\n",ask(a,b));} return 0 ;}/*
1 1
aaa 2
a a*/

上面这份代码有几个细节:注意建树的时候tmprt和rt不能混用,需分开,第二画图一下就可以发现对每一个节点建后缀树的时候都会新建一个新的空节点(这也是写完自己花了一下图才发现的),这样有个好处,那就是不需要做繁琐的坐标运算,因为否则你的trie数组的第二维就得开26*2这么大,第一维就是1e6就行,而现在新开一个空节点当根节点,保持了代码的统一性,就相当于完全就是新建一棵字典树,代码不需要动太多,减少出错率。

还有一点,ask的时候别忘了查完前缀的时候rt=trie[rt][27]这一步、、、不然肯定GG(因为你继续搜索相当于顺着正向的字典树查下去了)

AC代码2:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<unordered_map> 
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e6 + 5;
char s[55];
int trie[MAX][26];
int Hash[MAX*20];
int tot;
void insert(char str[],int a[]) {int rt = 0,len = strlen(str);for(int i = 0; i<len; i++) {int cur = str[i] - 'a';if(!trie[rt][cur]) trie[rt][cur] = ++tot;rt = trie[rt][cur];a[i] = rt;}
}
int ask(char str[]) {int res = 0,len = strlen(str),rt = 0;for(int i = 0; i<len; i++) {int cur = str[i] - 'a';if(trie[rt][cur] == 0) return -1;else rt = trie[rt][cur];}return rt;
}
unordered_map<ll,int>g;
int A[55],B[55];
int main()
{int n,m;cin>>n>>m;for(int w,i = 1; i<=n; i++) {scanf("%s%d",s,&w);insert(s,A);int len = strlen(s);reverse(s,s+len);insert(s,B);//至此,a和b数组的0~len-1都有对应的值了 for(int j = 0; j<len; j++) {for(int k = 0; k<len; k++) {ll HS = (ll)A[j] * 1000007 + B[k];//Hash[int(HS%mod)] = MX(Hash[int(HS%mod)],w);//因为权值w都是正数,所以不需要像那个代码一样unorderedmap的时候分存在和不存在这一说、、、(主要是这不是迭代器而是数组。。所以都已经分配空间了) if(!g.count(HS))g[HS]=w;else if(w>g[HS])g[HS]=w;}}}char a[55],b[55];while(m--) {scanf("%s%s",a,b);int lena = strlen(a);int lenb = strlen(b);reverse(b,b+lenb);int x = ask(a);int y = ask(b);int ans = -1;if(x!=-1&&y!=-1) {ll w=(ll)x*1000007+y;if(g.count(w))ans=g[w];}printf("%d\n",ans);} return 0 ;}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c 语言 while break,26 C 语言中的break和continue - C 语言基础教程

循环语句很好用&#xff0c;但是如果循环进行到一般想要跳出循环或者结束循环怎么办&#xff1f;那么那你需要 break 和 continue 语句。1. break 和 continue 的使用语法1.1 or 循环中使用 break 和 continuebreakfor (控制循环的变量; 循环判断条件; 循环变量增减变化){语句1…

【牛客 - 21302】被3整除的子序列(线性dp)

题干&#xff1a; 给你一个长度为50的数字串,问你有多少个子序列构成的数字可以被3整除 答案对1e97取模 输入描述: 输入一个字符串&#xff0c;由数字构成&#xff0c;长度小于等于50 输出描述: 输出一个整数 示例1 输入 复制 132 输出 复制 3 示例2 输入 复制 …

c语言链表实现数组逆置,数组与链表等顺序表逆置

一)数组的逆置(1)算法#indclude#define N 8main(){int array[N] {100,90,80,70,60,50,50,40};int i,j,t;for(i0,jN-1;i{t array[i];array[i] array[j];array[j] t;}for(i0,iprintf("%d",qlist.data[i])}(2)时间复杂度由于只需循环N/2即可完成逆置,所以时…

linux系统get命令详解,Ubuntu Linux系统下apt-get命令详解

整理了Ubuntu Linux操作系统下apt-get命令的详细说明,分享给大家。常用的APT命令参数&#xff1a;apt-cache search package 搜索包apt-cache show package 获取包的相关信息&#xff0c;如说明、大小、版本等sudo apt-get install package 安装包sudo apt-get install package…

*【Hihocoder - offer编程练习赛94 - A】最短管道距离(中位数)

题干&#xff1a; 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在一张2D地图上有N座城市&#xff0c;坐标依次是(X1, Y1), (X2, Y2), ... (XN, YN)。 现在H国要修建一条平行于X轴的天然气主管道。这条管道非常长&#xff0c;可以认为是一条平行于X轴的直线。…

android开发百度地图坐标偏差,利用百度地图Android sdk高仿微信发送位置功能及遇到的问题...

接触了百度地图开发平台半个月了&#xff0c;这2天试着模仿了微信给好友发送位置功能&#xff0c;对百度地图的操作能力又上了一个台阶我在实现这个功能的时候&#xff0c;遇到一些困难&#xff0c;可能也是别人将会遇到的困难&#xff0c;特在此列出1、在微信发送功能中&#…

*【牛客 1 - A】矩阵(字符串hash)

题干&#xff1a; 给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。 输入描述: 第一行两个整数n, m代表矩阵的长和宽&#xff1b; 接下来n行&#xff0c;每行m个字符&#xff08;小写字母&#xff…

*【洛谷 - P1025】数的划分(dfs 或 dp 或 母函数,第二类斯特林数Stirling)

题干&#xff1a; 题目描述 将整数n分成k份&#xff0c;且每份不能为空&#xff0c;任意两个方案不相同(不考虑顺序)。 例如&#xff1a;n7&#xff0c;k3&#xff0c;下面三种分法被认为是相同的。 1,1,5 1,5,1 5,1,1 问有多少种不同的分法。 输入输出格式 输入格式&am…

kali linux 截图 软件,Kali-Linux-Tools-Interface:针对Kali Linux的图形化Web接口

Kali-Linux-Tools-Interface在当今这个信息时代&#xff0c;数据是最有价值的资产&#xff0c;因此&#xff0c;广大用户和企业已成为网络攻击的主要目标。众所周知&#xff0c;信息安全专业人员都会使用一系列技术工具来协助他们的活动。但是设置环境&#xff0c;安装这些工具…

【牛客 - 188D 】愤怒(01滚动数组优化dp,括号匹配方案个数,tricks)

题干&#xff1a; 小w很生气 小w有一个长为n的括号序列 愤怒小w想把这个括号序列分为两个括号序列 小w想让分为的这两个括号序列同时合法 小w想知道一共有多少种划分方案 (划分的意思是划分为两个子序列) 注意两个序列是 A,B 和 两个序列是B,A 算两种方案,也就是同一位置位…

android adb 开机广播,Android中常用的adb指令

1、安装apkadb install filename.apk如:adb install C:\Users\zhijianhulian\Desktop\keystore\kingoroot.apk2、卸载apkadb uninstall apk包名如&#xff1a;adb uninstall com.kingoroot.cn3、启动activityadb shell am start -n 包名/activity完整包名地址如&#xff1a;adb…

ACM所有算法大全(持续更新)

转载自&#xff1a; http://blog.sina.com.cn/s/blog_adb6743801019h29.html ACM 所有算法 数据结构 栈&#xff0c;队列&#xff0c;链表哈希表&#xff0c;哈希数组堆&#xff0c;优先队列 双端队列 可并堆 左偏堆二叉查找树 Treap 伸展树并查集 集合计数问题 二分图的识别平…

android布局属性,Android 布局学习之——LinearLayout属性baselineAligned的作用及baseline...

相信大家对LinearLayout已经相当熟悉&#xff0c;但你们是否了解它的属性baselineAligned呢&#xff1f;Android官方文档是这么描述的&#xff1a;那到底这个属性是做什么用的呢&#xff1f;baselineAligned:基准线对齐。首先要解释什么是基准线&#xff0c;这个在中文中不常见…

【CodeForces - 1105C】Ayoub and Lost Array(线性计数dp)

题干&#xff1a; Ayoub had an array aa of integers of size nn and this array had two interesting properties: All the integers in the array were between ll and rr (inclusive).The sum of all the elements was divisible by 33. Unfortunately, Ayoub has lost h…

【牛客 - 373C】抓捕盗窃犯(连通图,思维,dfs 或 并查集)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/373/C 来源&#xff1a;牛客网 Q市发生了一起特大盗窃案。这起盗窃案是由多名盗窃犯联合实施的,你要做的就是尽可能多的抓捕盗窃犯。 已知盗窃犯分布于 N N个地点,以及第 i i个地点初始有 ai ai名盗…

android取消自动调试模式吗,Android进入调试模式的三种技巧

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;Android开发过程中难免会遇到各种问题&#xff0c;通常我们会通过打印Log日志或者Debug模式来分析问题。这里介绍下Android程序进入到Debug的多种方式&#xff0c;…

IMX6怎么移植最新Android,[IMX6Q][Android5.1]移植筆記 --- 無法掛載system文件系統

platform: imx6qos: Android5.1branch: l5.1.1_2.1.0-ga編譯好system image之后開機提示如下log&#xff0c;注意紅色部分:Freeing unused kernel memory: 432K (c0be3000 - c0c4f000)usb 1-1: USB disconnect, device number 2Console: switching to colour dummy device 80x3…

【牛客 - 373A】翻硬币问题(博弈,结论,分析)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/373/A 来源&#xff1a;牛客网 Alice和Bob正在玩一个很经典的游戏。 有 n n个硬币初始时全部正面朝上&#xff0c;每一轮Alice必须选择其中任意的恰好 m m枚硬币并将它们全部翻转&#xff0c;如果若…

opera android 7,Opera迷你浏览器 Opera Mini 7

包名&#xff1a;com.opera.mini.android全新的界面Opera Mini 6在所有地方都有了全新的形象.新的设计、新的皮肤,还有新的缩放和跳转按键,这都让Opera Mini 6变得更加好用分享功能Opera Mini 6中你可以将感兴趣的内容分享到你所在社交平台中去触屏的双指缩放这次Opera也支持触…

【POJ - 1456】Supermarket (贪心,优先队列 或并查集)

题干&#xff1a; A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an integral number of time units starting from the moment the sale begins. Each product takes precis…