算法专栏 ---- trie树,并查集

news2024/12/26 22:36:04

 trie树 

#include <iostream>
using namespace std;
const int N = 1000010;
int son[N][26],cnt[N],idx;
//明确前面两个数组以及idx的含义
//我们把son这个二维数组看成一个字典树
//本题要求26个字母,所以我们每个节点里面最多有26个儿子节点
//而我们本题要求字符串长度是100000个,所以son数组的N代表有100000层,对应的就是字符串长度
//为什么这样就可以呢,因为我们查找的字符串(只有26个字母)在查找的时候想象成树
//每次面临26种选择(26个字母)(也有点组合的意思),选择一种和当前匹配的,没有就说明没有匹配的
//idx是什么呢,我们怎么用数组来模拟的呢,我们怎么算是创建过这个节点了,我们son数组的元素为1
//就代表我们创建了这个节点,如果遇到这个节点之后我们就可以直接往下走,如果没有遇到,我们就
//不往下走,先创建在走,创建的过程就是idx++,就是走到当前元素为1时说明创建过了
//cnt数组表示以当前节点的值为终点的字符串个数

char str[N];
void insert(char str[])
{
    int p = 0;//p代表我们当前走到哪个位置了(把数组抽象成一棵树)
    for(int i = 0; str[i] != '\0';i++)//枚举插入的字符串,枚举的字符串抽象成路径
    {
        int u = str[i] - 'a';//映射到数组里,son数组一维数组的下标0代表的是a,1是b
        if(son[p][u] == 0) son[p][u] = ++idx;//每次进入判断是否创建过当前值的节点
        p = son[p][u];//走到下一层
    }
    cnt[p]++;//当前下标为终点的字符串个数++
}
int  inquire(char str[])
{
   int p = 0;
   for(int i = 0; str[i] != '\0';i++)
   {
       int u = str[i] - 'a';
       if(!son[p][u]) return 0;
       p = son[p][u];
   }
   return cnt[p];
}
int main()
{
    int n;
    cin>>n;
    for(int i = 0;i < n;i++)
    {
        char chose[2];
        cin>>chose>>str;
        if(chose[0] == 'I')
        {
            insert(str);
        }
        else
        {
            printf("%d\n",inquire(str));
        }
    }
    return 0;
}

并查集

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
//本题是模板题,所以我们先理解这道题的模板是什么
//本题的模板是并查集,那什么是并查集呢,其实你可以想象成一个树
//我们的字符串都是通过递归去搜索的,跟字典树类似
//但是并查集强在归并和询问的操作近乎O(1)的时间复杂度,可以快速将两个集合
//合并和快速查两个集合是否在同一个集合


//并查集的基本原理是什么呢,基本原理就是每个集合我们看成一颗小树,一颗大树里可能包含小树
//比方说一个字符串是一个集合,那么这棵大树可能就有好多字符串集合,
//那我们并查集是怎么快速实现合并和查询的呢,这就要说到并查集的编号了
//我们怎么去查找到这个集合呢,我们肯定得让他的根节点跟孩子节点编号不一样,我们才能找到
//我们的集合,在此我们设置P[x]为节点的编号,而p[x] == x 是根节点的编号
//我们的p[x]代表的是当前节点的父节点
//1.如何判断根节点 if(p[x] == x)
//2.如何从孩子节点求根节点的编号while(p[x]!=x) x = p[x];
//3.如何合并两个集合,假设编号是p[X],P[Y],前面提到过的我们抽象成一颗树,这棵树
//合并只需要把一个根节点作为另一个根节点的父节点即可
//在此,我们还需要优化一下,路径压缩法,等于说第一次查询过这个集合之后下次查询就是O(1)的
//时间复杂度,为什么呢,想象一下一棵树的高度只有2,根节点只有1个,这时我们查询集合的所以元素的话
//我们就只需要遍历这个集合就元素就行,不需要再去递归好几层了

//并查集模板最关键的点是在于写出find操作
const int N = 1000010;
int p[N];
int  find(int x)//返回要查找的元素的集合,递归查找
{
    if(p[x] != x)  p[x] = find(p[x]);//如果父节点不是根节点,那么就把接力棒给父节点
    //让父亲节点去找
    return p[x];//找到了就返回
}
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1;i <= n;i++) p[i] = i;
    while (m--)
    {
        char op[2];
        int a, b;
        scanf("%s%d%d",op,&a,&b);
        if (op[0] == 'Q')
        {
            if (find(a) == find(b)) printf("Yes\n");
            else printf("No\n");
        }
        else if(op[0] == 'M')
        {
            p[find(a)] = find(b);//找到a集合的根节点,把a集合的根节点查到b集合的根节点
        }
    }
   return 0;
}

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510000;
int p[N],d[N];
int n,m;
int find(int x)//路径压缩
{
    if(p[x] != x)//不是根节点的话
    {
        int t = find(p[x]);
        d[x] += d[p[x]]; 
        p[x] = t;
    }
    return p[x];
}

int main()
{
    cin>>n>>m;
    for(int i = 1;i <= N;i++)
    {
        p[i] = i;
    }
    int cnt = 0;
    for(int i = 1;i <= m;i++)
    {
        int op,a,b;
        cin>>op>>a>>b;
        if(a > n || b > n)
        {
            cnt++;
            continue;
        }
        int pa = find(a);
        int pb = find(b);
        if(op == 1)
        {
  if(pa == pb && (d[a] - d[b]) % 3){
                    //是在同一个集合的话,判断是否是同类
                //不是同类res++,是同类不用管
                    cnt++;
                }
                else if(pa != pb){
                    //不在同一个集合,判断是否同类
                //先建立两个集合的集合关系,为什么建立两个呢
                //因为能find找到说明必有根节点
                //本题根节点肯定存在,就算只有两个节点
                //我们也看成两个集合
                
                    p[p[a]] = pb;//让x集合的根节点作为y集合的根节点的孩子
                    //节点
                    
                    //建立之后还得更新一下距离关系,第一次进入的话其实
                    //并没有建立集合,也就是刚好是说了第一句话的时候
                    //第一句不同的x和y或者两个相同的x或者y我们默认为真话,
                    //默认为x和y同类并且建立关系(同类关系)
                    //所以x和y分别到当前建立好集合关系
                    //的根节点的距离一定要相等,所以距离
                    //就是d[x] + ?= d[y],这个问好是根节点到px的距离
                    d[pa] = d[b] - d[a];
                }
        }
        else
        {

               if(pa == pb && (d[a] - d[b] -1) %3){
                    //在同一个集合
                //并且不是x 吃 y的关系
                //c++中-n % n等于0
                    cnt++;
                }
                else if(pa != pb){
                //不是同一个集合的话,那么我们默认为
                //真话,x能吃掉y
                    p[p[a]] = pb;
                    //维护距离使得x能吃掉y
                    d[pa] = d[b] - d[a] + 1;
                }
        }
    }
    cout<<cnt<<endl;
    return 0;
}

 

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

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

相关文章

DL4J无法下载MNIST数据集解决 Server returned HTTP response code: 403 for URL解决方法

报错情况 报错如下&#xff1a; 16:45:41.463 [main] INFO org.nd4j.nativeblas.Nd4jBlas - Number of threads used for OpenMP BLAS: 6 16:45:41.497 [main] INFO org.nd4j.linalg.api.ops.executioner.DefaultOpExecutioner - Backend used: [CPU]; OS: [Windows 10] 16:4…

Sqlserver2012和Sqlserver2019数据库设置最大并行数解决数据库CPU高问题

请注意&#xff0c;最大并行数范围是0到CPU的实际逻辑核心数的最大值 SQL Server2019之前的版本&#xff0c;最大并行度默认值都是0&#xff0c;也就是无限制。SQL Server2019最大并行度默认值会根据CPU逻辑处理器数自动计算&#xff0c;如数值是8&#xff0c;那么也就是一个执…

时序预测 | Python实现ARIMA-CNN-LSTM差分自回归移动平均模型结合卷积长短期记忆神经网络时间序列预测

时序预测 | Python实现ARIMA-CNN-LSTM差分自回归移动平均模型结合卷积长短期记忆神经网络时间序列预测 目录 时序预测 | Python实现ARIMA-CNN-LSTM差分自回归移动平均模型结合卷积长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 时序预测 …

第23期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

Django开发使用DRF框架之创建纯净版框架步骤

使用Django开发时&#xff0c;遇到前后端分离的项目&#xff0c;需要创建一个纯净版的Django框架&#xff0c;在使用restframework框架时&#xff0c;有些Django自带的功能或者说是APP用不到&#xff0c;那需要怎么设置呢&#xff0c;需要解决哪些问题&#xff0c;请见下面的详…

《研发效能(DevOps)工程师》课程简介(三)丨IDCF

在研发效能领域中&#xff0c;【开发与交付】的学习重点在于掌握高效的开发工具和框架&#xff0c;了解敏捷开发方法&#xff0c;掌握持续集成与持续交付技术&#xff0c;以及如何保证应用程序的安全性和合规性等方面。 由国家工业和信息化部教育与考试中心颁发的职业技术证书…

【虹科干货】Redis企业版给DevOps团队带来了哪些价值?

内存太贵&#xff1f;现代化转型太难&#xff1f;还在花费精力维护数据库基础设施&#xff1f;Redis Enterprise 在开源版的基础上增加了一整套包含管理、自动化、弹性以及安全等方面的功能&#xff0c;使其更适合企业级的应用场景。那么&#xff0c;Redis Enterprise 如何能成…

防近视台灯有必要买吗?分享能够预防近视的专业护眼台灯

对于护眼台灯能够预防近视这件事&#xff0c;很多家长认为这是一种智商税的。其实不然&#xff0c;护眼台灯之所以能够预防近视&#xff0c;当然不是说只要使用了这种台灯&#xff0c;就真的不会近视了。首先我们要明白&#xff0c;台灯对于孩子而言是夜晚阅读书写时必不可少的…

nacos1.1.4 持久化数据库升级到 Mysql8.0.34

1 环境要求 CentOS 7、MySQL 8.0.34 2 安装步骤 2.1 docker拉取mysql 8.0.34命令 这样写时拉取最新版本&#xff0c;可以直接写到对应的版本 docker pull mysql:8.0docker pull mysql:8.0.342.2 docker images确认 2.3 安装运行mysql8.0容器 docker run -p 3307:3306 --n…

API文档自动生成

API文档自动生成 背景smart-doc配置效果图 背景 对于API接口文档自动生成&#xff0c;可能大家&#xff0c;最新想到的是用swagger&#xff0c;但是有以下问题&#xff1a; 对代码侵入太强版本升级&#xff0c;并不兼容不能生成各种类型的文档 所以&#xff0c;今天给大家推荐…

Java算法:二分查找

一、 二分查找注意 前提是数组必须是有序的&#xff0c;否则无法正常工作。如果数组不是有序的&#xff0c;需要先对数组进行排序&#xff0c;然后才能使用二分查找算法。 二、二分查找高效算法 二分查找也称为折半查找&#xff0c;是一种在有序数组中查找目标元素的算法。它的…

华纳云:centos系统中怎么查看cpu信息?

在CentOS系统中&#xff0c;我们可以使用一些命令来查看CPU的详细信息。下面介绍几个常用的命令&#xff1a; 1. lscpu lscpu命令可以显示CPU的架构、型号、核心数、线程数、频率等信息。 # lscpu 执行以上命令后&#xff0c;会输出类似以下内容&#xff1a; 2. cat /proc/…

【JAVA学习笔记】54 - 集合 - Set类、HashSet类、TreeSet类(难点)

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter14/src/com/yinhai/set_ Set类 一、基本介绍 1.无序(添加和取出的顺序不一致) ,没有索引[后面演示] 2.不允许重复元素&#xff0c;所以最多包含一个null 3.JDK API中Set接口的实现类有: …

jvs-logic逻辑引擎功能新增:逻辑凭证、自定义权限控制等等

新增: 1.新增逻辑复制功能&#xff1b;主要用于数据的同步和复制 2.逻辑新增权限设置功能&#xff1b; 每个逻辑可以设置不同的权限&#xff0c;逻辑页的功能权限配置默认是全部赋权给应用授权的相关人员&#xff0c;也可以按照自定义配置&#xff0c;如图所示&#xff0c;选…

rhcsa-数据流和重定向

cp cp 选项 源文件 目标文件 ****-a 复制目录的所有信息&#xff08;保留文件信息&#xff09; -p保留原文件的权限&#xff0c;所有者以及时间戳的信息 -r复制目录及所有子目录的所有文件 例&#xff1a; cp -p 复制的源文件 复制的目标路径 mv 作用&#xff…

ChatGLM2-6B下载与部署

0 写在前面 我们首先来看一下ChatGLM2-6B模型的requirements: protobuf transformers4.30.2 cpm_kernels torch>2.0 gradio mdtex2html sentencepiece accelerate sse-starlette streamlit>1.24.0可以看到&#xff0c;要求torch>2.0&#xff0c;这就产生了一个问题&…

解决uniapp的video标签和transition属性使用时出现错位的问题

template&#xff1a;三个视频都每个占满屏幕&#xff0c;点击按钮滚动最外层bgBox元素&#xff0c; style: 想要加上动画过渡效果&#xff1a; 这是显示第一个视频&#xff1a; 点按钮向上滑动滚动到第二个视频时&#xff1a; 视频错位了 &#xff0c;因为视频消失又出现的时候…

一款支持星座、干支、生肖、节气、节日、彭祖百忌、每日宜忌等超卷的日历工具库

大家好&#xff0c;我是凌览。 日常GitHub划水发现一款超级6的日历工具库lunar&#xff0c;它支持阳历、阴历、佛历和道历&#xff0c;甚至还玩上了星座、干支、生肖、节气、节日、彭祖百忌、每日宜忌、吉神宜趋、凶煞宜忌、吉神方位、冲煞、纳音、星宿、八字、五行、十神、建…

day58--动态规划16

583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结篇 第一题&#xff1a;两个字符串的删除操作 给定两个单词 word1 和 word2&#xff0c;找到使得 word1 和 word2 相同所需的最小步数&#xff0c;每步可以删除任意一个字符串中的一个字符。 示例&#xff1a; 输入: &qu…

单元测试学习

回顾测试理论基础 单元测试基础知识 什么是单元测试 单元测试流程、测试计划 测试策略设计、实现 单元测试 - 执行 HTML 报告生成 1 软件测试分类 目标 回顾测试理论知识-测试分类 1. 测 试分类 代码可见度上-划分分类&#xff1a; 1. 黑盒测试 2. 灰盒测试 3. …