【字典树(前缀树) 字符串】2416. 字符串的前缀分数和

本文涉及知识点

字典树(前缀树) 字符串

LeetCode 2416. 字符串的前缀分数和

给你一个长度为 n 的数组 words ,该数组由 非空 字符串组成。
定义字符串 word 的 分数 等于以 word 作为 前缀 的 words[i] 的数目。
例如,如果 words = [“a”, “ab”, “abc”, “cab”] ,那么 “ab” 的分数是 2 ,因为 “ab” 是 “ab” 和 “abc” 的一个前缀。
返回一个长度为 n 的数组 answer ,其中 answer[i] 是 words[i] 的每个非空前缀的分数 总和 。
注意:字符串视作它自身的一个前缀。

示例 1:
输入:words = [“abc”,“ab”,“bc”,“b”]
输出:[5,4,3,2]
解释:对应每个字符串的答案如下:

  • “abc” 有 3 个前缀:“a”、“ab” 和 “abc” 。
  • 2 个字符串的前缀为 “a” ,2 个字符串的前缀为 “ab” ,1 个字符串的前缀为 “abc” 。
    总计 answer[0] = 2 + 2 + 1 = 5 。
  • “ab” 有 2 个前缀:“a” 和 “ab” 。
  • 2 个字符串的前缀为 “a” ,2 个字符串的前缀为 “ab” 。
    总计 answer[1] = 2 + 2 = 4 。
  • “bc” 有 2 个前缀:“b” 和 “bc” 。
  • 2 个字符串的前缀为 “b” ,1 个字符串的前缀为 “bc” 。
    总计 answer[2] = 2 + 1 = 3 。
  • “b” 有 1 个前缀:“b”。
  • 2 个字符串的前缀为 “b” 。
    总计 answer[3] = 2 。
    示例 2:

输入:words = [“abcd”]
输出:[4]
解释:
“abcd” 有 4 个前缀 “a”、“ab”、“abc” 和 “abcd”。
每个前缀的分数都是 1 ,总计 answer[0] = 1 + 1 + 1 + 1 = 4 。

提示:

1 <= words.length <= 1000
1 <= words[i].length <= 1000
words[i] 由小写英文字母组成

字典树

字典树各节点记录子树数量。
针对每个word ,一次查询word[0…j] 子孙的数量,累加就可以了。

代码

核心代码

namespace NTmp {template<class TData = char, int iTypeNum = 26, TData cBegin = 'a'>class CTrieNode{public:~CTrieNode(){for (auto& [tmp, ptr] : m_dataToChilds) {delete ptr;}}CTrieNode* AddChar(TData ele, int& iMaxID){
#ifdef _DEBUGif ((ele < cBegin) || (ele >= cBegin + iTypeNum)){return nullptr;}
#endifconst int index = ele - cBegin;auto ptr = m_dataToChilds[ele - cBegin];if (!ptr){m_dataToChilds[index] = new CTrieNode();
#ifdef _DEBUGm_dataToChilds[index]->m_iID = ++iMaxID;m_childForDebug[ele] = m_dataToChilds[index];
#endif}m_dataToChilds[index]->m_iChildChildCount++;return m_dataToChilds[index];}CTrieNode* GetChild(TData ele){
#ifdef _DEBUGif ((ele < cBegin) || (ele >= cBegin + iTypeNum)){return nullptr;}
#endifreturn m_dataToChilds[ele - cBegin];}protected:
#ifdef _DEBUGint m_iID = -1;std::unordered_map<TData, CTrieNode*> m_childForDebug;
#endifpublic:int m_iLeafIndex = -1;int m_iChildChildCount = 0;protected://CTrieNode* m_dataToChilds[iTypeNum] = { nullptr };//空间换时间 大约216字节//unordered_map<int, CTrieNode*>    m_dataToChilds;//时间换空间 大约56字节map<int, CTrieNode*>    m_dataToChilds;//时间换空间,空间略优于哈希映射,数量小于256时,时间也优。大约48字节};template<class TData = char, int iTypeNum = 26, TData cBegin = 'a'>class CTrie{public:int GetLeadCount(){return m_iLeafCount;}CTrieNode<TData, iTypeNum, cBegin>* AddA(CTrieNode<TData, iTypeNum, cBegin>* par, TData curValue){auto curNode = par->AddChar(curValue, m_iMaxID);FreshLeafIndex(curNode);return curNode;}template<class IT>int Add(IT begin, IT end){auto pNode = &m_root;for (; begin != end; ++begin){pNode = pNode->AddChar(*begin, m_iMaxID);}FreshLeafIndex(pNode);return pNode->m_iLeafIndex;}template<class IT>CTrieNode<TData, iTypeNum, cBegin>* Search(IT begin, IT end){auto ptr = &m_root;for (; begin != end; ++begin){ptr = ptr->GetChild(*begin);if (nullptr == ptr){return nullptr;}}return ptr;}CTrieNode<TData, iTypeNum, cBegin> m_root;protected:void FreshLeafIndex(CTrieNode<TData, iTypeNum, cBegin>* pNode){if (-1 == pNode->m_iLeafIndex){pNode->m_iLeafIndex = m_iLeafCount++;}}int m_iMaxID = 0;int m_iLeafCount = 0;};}
class Solution {
public:vector<int> sumPrefixScores(vector<string>& words) {NTmp::CTrie<> trie;for (const auto& s: words) {trie.Add(s.begin(), s.end());}vector<int> vRet;for (const auto& s : words) {auto ptr = &trie.m_root;int cnt = 0;for (const auto& ch : s) {ptr = ptr->GetChild(ch);cnt += ptr->m_iChildChildCount;}vRet.emplace_back(cnt);}return vRet;}
};

测试用例

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){assert(v1[i] == v2[i]);}
}template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}int main()
{vector<string> words;{Solution slu;words = { "abc", "ab", "bc", "b" };auto res = slu.sumPrefixScores(words);Assert({ 5,4,3,2 }, res);}{Solution slu;words = {"abcd" };auto res = slu.sumPrefixScores(words);Assert({ 4 }, res);}
}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

【list】list库介绍 + 简化模拟实现

本节博客先对list进行用法介绍&#xff0c;再在库的基础上简化其内容和形式&#xff0c;简单进行模拟实现&#xff0c;有需要借鉴即可。 目录 1.list介绍1.1 list概述1.2相关接口的介绍 2.简化模拟实现3.各部分的细节详述3.1结点3.2迭代器细节1&#xff1a;迭代器用原生指针还是…

深入理解TCP滑动窗口协议

在计算机网络中&#xff0c;传输控制协议&#xff08;TCP&#xff09;是确保可靠数据传输的核心协议之一。TCP的可靠性和高效性部分得益于其滑动窗口机制。本文将详细介绍TCP滑动窗口协议的工作原理及其在实际中的应用。 什么是滑动窗口协议&#xff1f; 滑动窗口协议是一种用…

【Codesys】-执行第三方程序,或Windows脚本

该记录旨在解决RTE作为第一个Windows的一个exe程序不能调用其他程序的问题。 可以实现:在PLC界面打开第三方程序、在PLC界面关闭本机Windows操作系统 首先添加依赖库-SysProcess,3.5.17.0 然后在程序里执行相应的指令&#xff0c;该指令可以被Windows识别为类似于执行Bat文件…

国产操作系统上使用rsync恢复用户数据 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上使用rsync恢复用户数据 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在国产操作系统上使用rsync备份并还原用户数据的文章。rsync是一款功能强大的文件同步和备份工具&#xff0c;广泛用于Linux系…

河南乙级道路与桥梁资质年审材料准备要点解析

河南乙级道路与桥梁资质年审材料准备要点解析如下&#xff1a;河南宽信权经理 一、企业基本情况材料 营业执照副本复印件&#xff1a;确保复印件清晰、完整&#xff0c;并加盖企业公章。 企业章程&#xff1a;提供最新的企业章程&#xff0c;并加盖企业公章。此材料需反映企业…

代码随想录——从前序与中序遍历序列构造二叉树(Leetcode105)

题目链接 递归 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

Linux(三)

Linux&#xff08;三&#xff09; Linux网络配置管理网络基础知识 IP地址A类 由1个字节网络地址3个字节主机地址B类 由2个字节网络地址2个主机地址C类 由3个字节网络地址1个主机地址D类:主要用于组播E类:为将来使用保留 子网掩码子网掩码作用网关DNS服务器 Linux用户管理用户的…

如何看centos 有没有安装x11

在CentOS系统中&#xff0c;可以通过检查是否存在X11相关的包来判断是否安装了X11。你可以使用yum工具来查询是否安装了xorg-x11-server-Xorg包&#xff0c;这通常是X11服务器的包名。 打开终端&#xff0c;输入以下命令&#xff1a; yum list installed | grep xorg-x11-ser…

浅析部署架构中的GZone、RZone和CZone

在现代软件开发中&#xff0c;理解和应用各种技术概念是成功的重要因素。本文将详细介绍GZone、RZone和CZone三个概念&#xff0c;解释它们的定义、特点、功能及应用场景&#xff0c;并通过实际案例帮助读者更好地理解这些概念。 一、GZone 1.1 定义 GZone是指“Global Zone…

MTK Android9.0 给vendor下文件夹权限,用于读取文件列表

1.背景 最近在TV开发中遇到一个问题&#xff1a;如何判断设备烧录过HDCP KEY的问题&#xff0c;由于MTK的官方接口返回值并不准确&#xff0c;只能判断2.2是否烧录&#xff0c;不能准确判断1.4是否烧录过&#xff0c;因为HDCP 的KEY有两个&#xff0c;分别是1.4和2.2&#xff…

结构体常见问题

问题一: 结构体的自引用 错误: typedef struct _Pos{ int x; int y; struct _Pos z; }pos; 定义一个结构体&#xff0c;其内部又定义了一个同类的结构体变量&#xff0c;这是一种错误。(因为如果你在结构体内部定义自己类型的结构体变量&#xff0c;在定义结构体的…

Shell脚本零碎知识积累

1、使用While循环打印目录中的所有文件&#xff1a; #!/bin/bash# 定义要遍历的目录 directory"./"# 使用while循环读取目录中的文件 while read file doecho "Found file: $file" done < <(find "$directory" -maxdepth 1 -type f)最后一…

linux创建离线yum源给局域网机器使用

适用场景&#xff1a;在封闭的内网环境中&#xff0c;无法使用互联网进行安装各种rpm包的时候&#xff0c;离线yum源可以解决大部分问题&#xff0c;配置号后可直接使用yum进行安装包 1.准备好镜像源ISO&#xff1a; 例如以下示例&#xff0c;具体可参考自己的系统进行下载&a…

新书推荐:7.3 for语句

本节必须掌握的知识点&#xff1a; 示例二十四 代码分析 汇编解析 7.3.1 示例二十四 ■for语句语法形式&#xff1a; for(表达式1;表达式2;表达式3) { 语句块; } ●语法解析&#xff1a; 第一步&#xff1a;执行表达式1&#xff0c;表达式1初始化循环变量&#xff1b; …

MATLAB基础应用精讲-【数模应用】贝叶斯优化

目录 前言 算法原理 朴素贝叶斯算法核心思想 示例 贝叶斯定理

【错题集-编程题】kotori 和迷宫(BFS / DFS)

牛客对应题目链接&#xff1a;kotori和迷宫 (nowcoder.com) 一、分析题目 迷宫问题的扩展。 二、代码 #include <iostream> #include <cstring> #include <queue>using namespace std;const int N 35; int x1, y1; // 标记起点位置 int n, m; char arr[N][…

Java实现抢红包算法——详细注释,标准语法

package learn;import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Random;public class RobRedPacket {// 发红包算法&#xff0c;金额参数以分为单位public static List<Integer> divideRedPacket(Integer totalAmoun…

电机控制系列模块解析(23)—— 同步机初始位置辨识

一、两个常见问题 为什么感应电机&#xff08;异步机&#xff09;不需要初始位置辨识&#xff1f;&#xff08;因此感应电机转子磁场在定子侧进行励磁&#xff0c;其初始位置可以始终人为定义为0&#xff09; 为什么同步磁阻电机需要初始位置辨识&#xff1f;&#xff08;因为…

【前端每日基础】day22——js控制结构

循环语句用于重复执行代码块。 for 循环 常用于需要精确控制循环次数的情况。 for (let i 0; i < 5; i) {console.log("Iteration:", i); }while 循环 当条件为真时重复执行代码块&#xff0c;适用于循环次数不确定但条件明确的情况。 let i 0;while (i <…

五分钟搭建一个Suno AI音乐站点

五分钟搭建一个Suno AI音乐站点 在这个数字化时代&#xff0c;人工智能技术正以惊人的速度改变着我们的生活方式和创造方式。音乐作为一种最直接、最感性的艺术形式&#xff0c;自然也成为了人工智能技术的应用场景之一。今天&#xff0c;我们将以Vue和Node.js为基础&#xff…