2024杭电多校(4) 1008. 树形DNA【01Trie、哈希】

news2024/9/20 22:29:56
题意

给定两颗二叉树 S S S T T T,如果对于 S S S 的某个子树 S ′ S^\prime S,删除若干个(或不删除)其子树后,可以和 T T T 相同(左子树与左子树匹配,右子树与右子树匹配),那么称 S ′ S^\prime S T T T 匹配

统计 S S S 中有多少个子树 S ′ S^\prime S T T T 匹配
保证 T T T叶子节点最多只有 20 20 20

1

思路

首先我们可以将 T T T 看成是一颗 01 T r i e 01 Trie 01Trie,假设 T T T k ( k ≤ 20 ) k(k \leq 20) k(k20) 个叶子,那么 T T T 就可以看成是插入了 k k k 01 01 01 串后的 T r i e Trie Trie,对于 S ′ S^\prime S 也看成是一颗 01 T r i e 01Trie 01Trie

那么问题转化为了:在每一个 S ′ S^\prime S 子树里,确定是否可以找到所有 k k k 01 01 01 串是从 S ′ S^\prime S 这个节点延伸下去的,即这 k k k 个串包含在 S ′ S^\prime S 这颗 T r i e Trie Trie

注意到 k k k 个串肯定两两不同,所以我们可以在 S S S d f s dfs dfs 来统计,对于当前节点 u u u,我们维护当前深度,以及 d f s dfs dfs 下来的路径,那么我们枚举 k k k 01 01 01 串,看看这些串是不是 u u u 结尾的某个后缀,即对于 s i s_i si,如果 s i s_i si 是以 u u u 结尾的串,那么 u u u ∣ s i ∣ |s_i| si 级祖先的 c n t cnt cnt + 1 +1 +1
字符串匹配同样可以在 d f s dfs dfs 过程中维护 h a s h hash hash 数组

d f s dfs dfs 完后, c n t = k cnt = k cnt=k 的那些点就是题目要求的点 S ′ S^\prime S

时间复杂度: O ( m + n k ) O(m + nk) O(m+nk)

#include<bits/stdc++.h>
#define fore(i,l,r)	for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;

const int INF=0x3f3f3f3f;
const long long INFLL=1e18;

typedef long long ll;

const int N = 300005;
const int P = 1313;

struct Tree{
    int n;
    std::vector<int> l, r;
    Tree(int n = 0){
        this -> n = n;
        l.assign(n + 1, 0);
        r.assign(n + 1, 0);
    }
    
    void set(int n = 0){
        this -> n = n;
        l.assign(n + 1, 0);
        r.assign(n + 1, 0);
    }
};

struct Seq{
    int len;
    ull w; //哈希值
};

Tree S, T;
ull Pow[N];
std::vector<Seq> leaf; //不超过20个01串
ull hash[N]; //搜索过程中的前缀哈希
std::vector<int> ans;
int cnt[N];
std::vector<int> pt; //dfs过程中的访问路径

inline ull get_hash(int l, int r){
    return hash[r] - hash[l - 1] * Pow[r - l + 1];
}

void dfs0(int u, ull val, int len){
    if(!T.l[u] && !T.r[u]){
        leaf.push_back({len, val});
        return;
    }
    if(T.l[u]) dfs0(T.l[u], val * P + 1, len + 1);
    if(T.r[u]) dfs0(T.r[u], val * P + 2, len + 1);
}

void dfs1(int u, int dep){
    cnt[u] = 0;
    pt.push_back(u);
    for(auto [len, w] : leaf)
        if(len <= dep){
            ull val = get_hash(dep - len + 1, dep);
            if(w == val) ++cnt[pt[dep - len]];
        }

    if(S.l[u]){
        hash[dep + 1] = hash[dep] * P + 1;
        dfs1(S.l[u], dep + 1);
    }
    if(S.r[u]){
        hash[dep + 1] = hash[dep] * P + 2;
        dfs1(S.r[u], dep + 1);
    }

    if(cnt[u] == leaf.size()) ans.push_back(u);
    pt.pop_back();
}

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    Pow[0] = 1;
    fore(i, 1, N) Pow[i] = Pow[i - 1] * P;
    int t;
    std::cin >> t;
    while(t--){
        int n, m;
        std::cin >> n;
        S.set(n);
        fore(i, 0, n){
            std::cin >> S.l[i] >> S.r[i];
        }
        std::cin >> m;
        T.set(m);
        fore(i, 0, m){
            std::cin >> T.l[i] >> T.r[i];
        }

        leaf.clear();
        dfs0(0, 0, 0);

        ans.clear();
        pt.clear();
        dfs1(0, 0);

        std::sort(ALL(ans));
        std::cout << ans.size() << endl;
        fore(i, 0, ans.size()) std::cout << ans[i] << " \n"[i == ans.size() - 1];
    }

    return 0;
}

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

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

相关文章

C++入门基础知识

在之前我们学习了C语言和初阶数据结构的相关知识&#xff0c;现在已经有了一定的代码能力和对数据结构也有了基础的认识&#xff0c;接下来我们将进入到新的专题当中&#xff0c;这个专题就是C。在C中我们需要花费更大的精力和更长的时间去学习这门建立在C语言基础之上的计算机…

新一代AI软件基础设施 | ZStack AIOS平台“智塔”发布

新一代 IT 基础设施&#xff0c;将从通用算力云平台转型为AI算力AIOS平台。 AI正在重构世界。正如世界是立体的&#xff0c;AI重构也正从多维度开启&#xff1a;基础设施重构&#xff0c;业务应用重构&#xff0c;交互模式重构&#xff0c;数据价值重构&#xff0c;生态系统重…

移动IP:让你的设备随时随地保持连接

随着无线网络技术的迅猛发展&#xff0c;在移动中进行数据通信已成为可能。成千上万的人正在使用移动设备畅享互联网&#xff0c;无论是在火车上、汽车内&#xff0c;还是在其他移动场景中。本文将带你了解移动IP&#xff08;Mobile IP&#xff09;的工作原理及其对网络应用的影…

LLM在线理解;神将网络理解;transform架构

目录 LLM在线理解 神将网络理解 transform架构 模型的子结构: 三个计算 计算1 计算2 计算3 LLM在线理解 LLM Visualization 神将网络理解 transform架构 模型的子结构: 词向量(Embedding) 前馈神经网络(Feed Forward) 残差连接(Add)和层标准化(Norm) 线性层(Linear…

Python版本和cuda版本不匹配解决办法

一、检查版本是否匹配 使用Python进入控制台&#xff0c;然后执行&#xff1a; >>>print(torch.cuda.is_available())如果输出为 False&#xff0c;则说明不匹配 退出Python环境&#xff0c;再检查系统版本&#xff1a; exit()nvcc -V 二、安装 去官网 PyTorch …

转载一篇关于对Linux磁盘部分mount和挂载的解释

转载自: http://t.csdnimg.cn/V3lgahttp://t.csdnimg.cn/V3lga

3_stm32_pwm呼吸灯

到目前已经可以进行基础的Led亮灭控制、使用定时器中断控制Led的亮灭。但是发现Led只有“亮”和 “灭”两种状态&#xff0c;那是否可以有更多状态&#xff1f;如何有更多状态呢&#xff1f;更进一步的想法&#xff0c;Led亮是有了电压差&#xff0c;其中一端是地&#xff0c;那…

C#:具体类=>抽象类=>接口的变化过程详解

文章目录 简单复习继承与多态具体类抽象类及成员使用语法 接口抽象类到接口的进化 简单复习继承与多态 下面,我用一个交通工具的例子来快速复习一下. 1.首先我定义一个基类Vehicle,代表交通工具的总称.里面定义了一个可被重写的成员方法Run. class Vehicle{public virtual voi…

Python Flask+Echarts实现葡萄酒质量的影响因素分析可视化

提示&#xff1a;本文章参考了哔哩哔哩的python课程李巍老师的 视频教程 文章目录 前言一、相关技术1.Flask2.Echarts3.词云 二、代码部分1.5个前端页面&#xff1a;2.代码 效果图 前言 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析&#xff0c;将它们加以汇总…

代码随想录算法训练营第六天(一)|242.有效的字母异位词

LeetCode 242 有效的字母异位词 题目&#xff1a; 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异位词。 示例 1: 输入: s "anagram&q…

韦东山嵌入式linux系列-mmap

应用程序和驱动程序之间传递数据时&#xff0c;可以通过read、 write函数进行。这涉及在用户态 buffer 和内核态 buffer 之间传数据&#xff0c;如下图所示 应用程序不能直接读写驱动程序中的buffer&#xff0c;需要在用户态 buffer 和内核态 buffer 之间进行一次数据拷贝。这种…

6.1.面向对象技术-面向对象相关概念

基本概念 对象&#xff1a;基本的运行实体&#xff0c;为类的实例&#xff0c;封装了数据和行为的整体(数据和行为就是属性和方法)&#xff0c;如学生、汽车等真实存在的实体。对象具有清晰的边界、良好定义的行为和可扩展性。 学生有张三、李四等。张三就是具体的个体&#xf…

Java哈希算法

哈希算法 哈希算法1.概述2.哈希碰撞3.常用的哈希算法4.哈希算法的用途4.1校验下载文件4.2存储用户密码MD5加密5.SHA-1加密小结&#xff1a; 哈希算法 1.概述 哈希算法&#xff08;Hash&#xff09;又称摘要算法&#xff08;Digest&#xff09;&#xff0c;它的作用是&#xf…

OrangePi AIpro学习3 —— vscode开发昇腾DVPP程序

目录 一、VScode配置 1.1 下载和安装 1.2 安装和配置需要的插件 二、构建项目 2.1 项目架构 2.2 解决代码高亮显示 2.3 测试编译 2.4 总结出最简单的代码 2.5 vscode报错找不到头文件解决方法 三、代码简单讲解 3.1 初始化部分 3.2 拷贝数据到NPU显存中 3.3 准备裁…

Leetcode每日一题之仅仅反转字母(C++)

在学习之余对于知识的巩固也尤为重要&#xff0c;不论难度高低&#xff0c;都会对代码的理解有所加深&#xff0c;下面我们开始练习 思路解析 关于本题的核心思路就是如何判断字符串中元素是否为字母以及如何遍历字符串以达到仅反转的目的&#xff0c;这里用到的知识就是关于 s…

【数据结构与算法 | 二叉树篇】AVL树

1. 前言 AVL树是一种自平衡的二叉搜索树。为什么会出现AVL树。众所周知&#xff0c;虽然普通的二叉搜索树的平均时间复杂度为O(logn)&#xff0c;但最差的情况的时间复杂度为O(n)。为了避免最差的这种情况&#xff0c;出现了AVL树。 我们规定&#xff1a;如果树有个节点它的左…

大模型LLM——微调的七种方法

大模型的七种微调方法 文章目录 大模型的七种微调方法1. LoRA2. QLoRA3. 适配器调整4. 前缀调整5. 提示调整6. P-Tuning7. P-Tuning v2 1. LoRA LoRA的主要步骤包括&#xff1a; 选择微调目标权重矩阵&#xff1a;首先在大型模型&#xff08;如GPT&#xff09;中识别需要微调…

学习vue3 五,传送,缓存组件以及过渡和过渡列表

目录 Teleport传送组件 keep-alive缓存组件 transition动画组件 1. 过渡的类名 2. 自定义过渡class名 3. transition的生命周期 4.appear transition-group 1. 过渡列表 2. 列表的移动过渡 3. 状态过渡 Teleport传送组件 Teleport Vue 3.0新特性之一。 Teleport 是一…

AI技术如何重塑企业EHS安全健康环保体系,附实践案例

随着人工智能技术的快速发展&#xff0c;其在环境、健康和安全&#xff08;EHS&#xff09;管理领域的应用日益广泛。AI技术通过大数据分析、模式识别和预测建模等手段&#xff0c;为EHS管理提供了新的视角和工具。这一变革不仅提升了风险评估和事故预防的效率&#xff0c;同时…

Can‘t use Subversion command line client:svn不能使用Subversion命令行客户端:svn

1、导入idea中会报Can’t use Subversion command line client… 2、在提交svn代码的时候&#xff0c;出现这样的错误&#xff1a;Can’t use Subversion command line client: svn Probably the path to Subversion executable is wrong. Fix it. 问题原因&#xff1a;在安…