华为2021批笔试题解

总结:数据结构fw惨遭翻车…呜呜呜

T1

题目大意:给出两个长度为k的字符串 a , b a,b a,b,两个长度为n的字符串 c , d c,d c,d ( k < = n ) (k<=n) (k<=n),求一个最小的 l l l,使得在 c , d c,d c,d中l开头的长度为k的子串刚好与 a , b a,b a,b匹配。
n , k < = 1 e 6 n,k<=1e6 n,k<=1e6

来了来了!!又又又又是笔试喜闻乐见必有的hash题!!!

(真就连着n场都有hash呗,大家都懂了吧,学好hash,笔试必过.jpg)

C++代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ull unsigned long long
#define maxn 10000005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline int read()
{
    
    
	int x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {
    
    if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {
    
    x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}

ull h1[maxn],h2[maxn],p1,p2,B[maxn];
int n,k,x;

inline ull gh(int l,int r,int opt)
{
    
    
	if(opt==1) return h1[r]-h1[l-1]*B[r-l+1];
	else return h2[r]-h2[l-1]*B[r-l+1];
}

int main()
{
    
    
	freopen("t1.in","r",stdin);
	k=read(); B[0]=1; rep(i,1,maxn-5) B[i]=B[i-1]*233;
	rep(i,1,k) x=read(),p1=p1*233+x;
	rep(i,1,k) x=read(),p2=p2*233+x;
	n=read();
	rep(i,1,n) x=read(),h1[i]=h1[i-1]*233+x;
	rep(i,1,n) x=read(),h2[i]=h2[i-1]*233+x;
	int F=0;
	rep(l,1,n)
	{
    
    
		int r=l+k-1; if(r>n) break;
		ull x1=gh(l,r,1),x2=gh(l,r,2);
		if(x1==p1&&x2==p2) {
    
    F=l; break;}
	}
	cout<<F<<endl;
	return 0;
}

T2

题目大意:给出n*m的矩阵,单次可以向四方向中小于自己权值的地方走,要求自选一个起点,求一条长度最长的路径。
n , m < = 1000 n,m<=1000 n,m<=1000

直接放原题链接吧: S H O I 2002 SHOI2002 SHOI2002 滑雪

记忆化搜索,考虑 d p [ i ] [ j ] dp[i][j] dp[i][j]为在 ( i , j ) (i,j) (i,j)位置的最长路。

那么由于每个点只会被dfs一遍,所以整体复杂度就是 O ( n ∗ m ) O(n*m) O(nm)了…

可能不太好理解,但是详见代码吧…代码挺是很好理解的。

Java代码:

import java.io.*;
import java.util.*;


public class zbr01
{
    
    
	public static int [][]a=new int [1005][1005];
	public static int [][]dp=new int [1005][1005];
	public static int [][]k={
    
    {
    
    1,0},{
    
    0,1},{
    
    -1,0},{
    
    0,-1}};
	public static int n,m,ans;
	
	public static int dfs(int x,int y)
	{
    
    
		if(dp[x][y]!=0) return dp[x][y];
		for(int i=0;i<=3;i++)
		{
    
    
			int tx=x+k[i][0],ty=y+k[i][1];
			if(tx<1||ty<1||tx>n||ty>m||a[tx][ty]>=a[x][y]) continue;
			dp[x][y]=Math.max(dp[x][y],1+dfs(tx,ty));
		}
		return dp[x][y];
	}

	
	public static void main(String[] args)
	{
    
    
		Scanner S=new Scanner(System.in);
		n=S.nextInt(); m=S.nextInt();
		for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=S.nextInt();
		for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans=Math.max(ans,dfs(i,j));
		System.out.println(ans+1);
	}
}

T3

题目大意:给出一颗固定形态,根节点的点权二叉树,求一条“只能向下走的”xor路径的最大值(xor路径权值为:路径上所有节点的异或值)。
n < = 1 e 5 n<=1e5 n<=1e5

看错题无数次…

(前置知识)
首先考虑这样一个问题“在长度为n的数列中,选择两个数进行xor的最大值”。
这个问题可以使用01trie解决…大家可以去百度学习一下…

那么这个问题中,我们考虑首先预处理出, w [ x ] w[x] w[x]为x到根节点的路径xor值,那么一条只能向下走的路径xor值,便转换为了 w[x]^(w[所有父节点])的max。

这个部分可以用以下伪代码表示:

void dfs(int u)
{
    
    
	trie插入当前值;
	trie查询当前的xor最大值
	dfs(儿子节点);

	trie删除当前值;
}

即可完成题目要求。

(由于弱菜博主突然智障…忘了怎么写trie删除…写了个可持久化01trie…最后也没能调试出来…呜呜呜

upd:
吐槽:怎么好像大家 O ( n 2 ) O(n^2) O(n2)的都被放过了啊…强烈谴责…啥数据啊,出题人写题都不考虑卡掉大暴力吗…强烈谴责!!!直接造一条链都能卡掉吧…这数据太不合格了hhh

猜你喜欢

转载自blog.csdn.net/qq_38649940/article/details/108501724
今日推荐