当前位置: 首页 > news >正文

Leetcode 2851. String Transformation

  • Leetcode 2851. String Transformation
    • 0. 吐槽
    • 1. 算法思路
      • 1. 整体思路
      • 2. 字符串匹配优化
    • 2. 代码实现
  • 题目链接:2851. String Transformation

0. 吐槽

这道题多少有点坑爹,题目本身挺有意思的,是一道数组题目,其实用数学方法直接可以写出结果的数学表达式,因此做的时候成就感非常强。

但是,坑爹的来了,谁会想到这道题最终卡人的是数组匹配算法,真心晕菜!!!

举个不太恰当的例子,就像是你去复原一个魔方,你想了n久,终于想到了魔方的复原方法,然后到了考场上面,面试官给了你一块木头和一把锯子,让你先做个魔方然后再复原,还限时2h……

就尼玛坑爹啊!!!

不过万幸,总算是搞定了,顺道也优化了一下字符串的匹配算法,虽然非我所愿,但多少也有点成就感吧……

1. 算法思路

1. 整体思路

这一题整体思路上可以视为一道数组题目。

显然的,对于一个长度为 n n n的字符串s,我们经过 k k k此操作之后可能的操作方式总数有 ( n − 1 ) k (n-1)^{k} (n1)k种。

我们假设第 k k k次操作之后字符串s恰好变为t的操作方式总数为 a k a_k ak,那么显然我们有如下递推公式:

a k = a k − 1 × ( m − 1 ) + ( ( n − 1 ) k − 1 − a k − 1 ) × m = m ⋅ ( n − 1 ) k − 1 − a k − 1 \begin{aligned} a_k &= a_{k-1} \times (m-1) + ((n-1)^{k-1} - a_{k-1}) \times m \\ &= m \cdot (n-1)^{k-1} - a_{k-1} \end{aligned} ak=ak1×(m1)+((n1)k1ak1)×m=m(n1)k1ak1

其中, m m m表示s的所有循环字符串(至多经过一次操作之后得到的字符串)当中t的个数,亦即,s可以通过 m m m种旋转方式直接变为t

此时,我们由上述递推公式,不难迭代写出:

a k = m ⋅ ( n − 1 ) k − 1 − a k − 1 a k − 1 = m ⋅ ( n − 1 ) k − 2 − a k − 2 ⋯ a 1 = m ⋅ ( n − 1 ) 0 − a 0 \begin{aligned} a_k &= m \cdot (n-1)^{k-1} - a_{k-1} \\ a_{k-1} &= m \cdot (n-1)^{k-2} - a_{k-2} \\ \cdots \\ a_1 &= m \cdot (n-1)^{0} - a_{0} \end{aligned} akak1a1=m(n1)k1ak1=m(n1)k2ak2=m(n1)0a0

我们分别带入之后即可得到 a k a_k ak的表达式如下:

a k = ( − 1 ) k a 0 + m ∑ i = 0 k − 1 ( − 1 ) k − 1 − i ⋅ ( n − 1 ) i = ( − 1 ) k a 0 + m ⋅ ( n − 1 ) k − ( − 1 ) k n \begin{aligned} a_{k} &= (-1)^{k} a_0 + m \sum\limits_{i=0}^{k-1} (-1)^{k-1-i} \cdot (n-1)^i \\ &= (-1)^{k} a_0 + m \cdot \frac{(n-1)^k - (-1)^k}{n} \end{aligned} ak=(1)ka0+mi=0k1(1)k1i(n1)i=(1)ka0+mn(n1)k(1)k

因此,事实上这道题我们可以通过 n , m , k n,m,k n,m,k的值直接算出我们的最终答案。

剩下的问题就是 n , m n,m n,m的求解了,其中 n n n是显然的,剩下的就是 m m m的求解了,本来其实就是将s再拼接一份然后看一下新组成的这个字符串当中t一共出现的次数就行了,用伪代码表示就是:

n = len(s)
ns = s + s[:-1]
m = len([i for i in range(n) if ns[i:i+n] == t])

结果没想到这里居然一直超时,最后这道题大部分的时候居然都集中在了解决这个问题上面,也是醉了……

下面,我们就来看一下我们具体对于这个问题的优化。

2. 字符串匹配优化

如前所述,这里事实上我们可以将问题抽象为如下问题:

已知两个字符串st,问s当中t一共出现过多少次。

因此这里其实就是一个字符串匹配的问题,不过我们可以对其进行一下优化:

  • 如果s当中的某一段已经和t匹配上了(假设起始坐标为i),此时我们就可以通过t本身的特性,找到t当中最接近头部的某个位置idx,满足t[idx:] == t[:n-idx],此时我们可以直接跳转到这个位置,然后比较子串t[n-idx:]s[i+n:i+n+idx]是否一致即可判断新的这个子串s[i+idx:i+idx+n]是否等于t,而无需判断中间的位置以及完整地判断这两个子串是否相同。

此时,问题就简化到了如何求得t当中最接近头部的某个位置idx,满足t[idx:] == t[:n-idx],而这个可以通过z-algorithm来进行快速实现,关于这部分的内容,我们之前已经写过了一个博客(经典算法:Z算法(z algorithm))对其进行过整理了,这里我们就不再展开赘述了。

2. 代码实现

综上,我们就可以给出我们最终的python代码实现如下:

def z_algorithm(s):n = len(s)z = [0 for _ in range(n)]l, r = -1, -1for i in range(1, n):if i > r:l, r = i, iwhile r < n and s[r-l] == s[r]:r += 1z[i] = r-lr -= 1else:k = i - lif z[k] < r - i + 1:z[i] = z[k]else:l = iwhile r < n and s[r-l] == s[r]:r += 1z[i] = r-lr -= 1z[0] = nreturn zdef find_all(s, t):l, n = len(s), len(t)prefix = z_algorithm(t)nxt, m = n, 0for i in range(1, n):if i + prefix[i] == n:nxt = im = prefix[i]breakidx = 0cnt = 0while idx < l:idx = s.find(t, idx)if idx == -1:breakcnt += 1if nxt < n:while idx+n < l and t[m:] == s[idx+n:idx+n+nxt]:idx = idx+nxtcnt += 1idx += 1return cntclass Solution:def numberOfWays(self, s: str, t: str, k: int) -> int:MOD = 10**9+7n = len(s)m = find_all(s+s[:-1], t)f0 = 0 if s != t else 1fk = f0 * pow(-1, k) + m * pow(n, -1, MOD) * (pow(n-1, k, MOD) - pow(-1, k))return fk % MOD

提交代码评测得到:耗时801ms,占用内存41.1MB。

值得一提的是,截至23.9.10晚间,当前这个执行效率远远高于其他python提交的算法执行效率(其他实现当中最快的执行时间为3167ms),多少也是让我感觉挺有成就感的……

相关文章:

Leetcode 2851. String Transformation

Leetcode 2851. String Transformation 0. 吐槽1. 算法思路 1. 整体思路2. 字符串匹配优化 2. 代码实现 题目链接&#xff1a;2851. String Transformation 0. 吐槽 这道题多少有点坑爹&#xff0c;题目本身挺有意思的&#xff0c;是一道数组题目&#xff0c;其实用数学方法…...

在PHP8中对数组进行计算-PHP8知识详解

在php8中&#xff0c;提供了丰富的计算函数&#xff0c;可以对数组进行计算操作。常见的计算函数如下几个&#xff1a;array_sum()函数、array_merge()函数、array_diff()函数、array_diff_assoc()函数、array_intersect()函数、array_intersect_assoc()函数。 1、array_sum()函…...

Android BottomSheetDialog最大展开高度问题

修改界面的时候遇到了这个问题,这个问题比较简单,网上解决方案也很多,这是 peekHeight 半展开高度,毕竟只是 dialog,全铺满就我们不必考虑 dialog 了 方法是在DialogFragment初始化dialog时处理 companion object {/*** 设置弹窗高度 默认展开无折叠情况 */ const val …...

记录Linux部署人脸修复GFPGAN项目Docker Python 使用

记录Linux 服务器使用人脸修复GFPGAN 项目 1:阿里云安装docker,用docker 是隔离环境,Python环境还真是麻烦… https://help.aliyun.com/zh/ecs/use-cases/deploy-and-use-docker-on-alibaba-cloud-linux-2-instances 2:关于docker 镜像,想找个好的镜像也是很难,百度吧,很多Li…...

如何编写可重入的函数?

编写可重入&#xff08;reentrant&#xff09;的函数是在多线程环境或并发编程中非常重要的任务。可重入函数是一种可以安全地被多个线程同时调用的函数&#xff0c;而不会导致数据竞争或不一致性的函数。在C语言中&#xff0c;编写可重入函数需要遵循一些特定的规则和技巧。本…...

使用纯C语言定义通用型数据结构的方法和示例

文章目录 前言以实现优先队列来描述实现思想基本类型的包装类型比较函数演示总结 前言 最近一段时间在复习数据结构和算法&#xff0c;用的C语言&#xff0c;不得不说&#xff0c;不学个高级语言再回头看C语言根本不知道C语言的强大和完美&#xff0c;不过相比之下也有许多不便…...

数据结构基础8:二叉树oj+层序遍历。

二叉树oj层序遍历 题目一&#xff1a;二叉树的销毁&#xff1a;方法一&#xff1a;前序遍历&#xff1a;方法二&#xff1a;后序遍历&#xff1a; 题目二&#xff1a;二叉树查找值为x的节点方法一&#xff1a;方法二&#xff1a;方法三&#xff1a; 题目三&#xff1a;层序遍历…...

Spring注解家族介绍:@RestController

前言&#xff1a; Spring Boot可以说是当前JAVA最为重要的一个框架&#xff0c;而Spring Boot的基石Spring中有着丰富的注解&#xff0c;因此我们会利用几篇文章来讲解我目前学到的各种注解&#xff0c;因此本类型文章的篇幅会比较短&#xff0c;主要着重于介绍各个注解。 目录…...

rocketmq

&#x1f353;代码仓库 https://gitee.com/xuhx615/rocket-mqdemo.git &#x1f353;基本概念 ⭐生产者(Producer)&#xff1a;消息发布者⭐主题&#xff08;Topic&#xff09;&#xff1a;topic用于标识同一类业务类型的消息⭐消息队列&#xff08;MessageQueue&#xff09…...

JAVA成员变量首字母小写,第二个字母大写报错问题(原因:Lombok与Spring冲突)

1、问题现象&#xff1a; JAVA类里定义成员变量使用首字母小写&#xff0c;第二个字母大写 Getter Setter public class BrandQueryObject extends QueryObject{private String pName; }结果页面报错&#xff0c;无法找到类型为 cn.wolfcode.ssm.query.BrandQueryObject 的对象…...

Python入门教程 |Python 错误和异常

Python3 错误和异常 作为 Python 初学者&#xff0c;在刚学习 Python 编程时&#xff0c;经常会看到一些报错信息&#xff0c;在前面我们没有提及&#xff0c;这章节我们会专门介绍。 Python 有两种错误很容易辨认&#xff1a;语法错误和异常。 Python assert&#xff08;断…...

API商品接口对接使用:从理论到实践

随着电子商务的飞速发展&#xff0c;API商品接口已成为现代电子商务应用程序不可或缺的一部分。通过API商品接口&#xff0c;开发者可以轻松地从其他应用程序或服务中获取商品信息&#xff0c;实现快速、高效的电子商务功能。本文将探讨API商品接口的概念、对接使用的方法以及一…...

解决stable diffusion webui1.6 wd1.4 tagger加载失败的问题

由于webui源码的变化&#xff0c;需要修改两个地方的import 1.tagger/ui.py # 第十行 # from webui import wrap_gradio_gpu_call # 原代码 from modules.call_queue import wrap_gradio_gpu_call1.preload.py # 第4行开始 # from modules.shared import models_path # 原…...

Python学习-实现简单的http服务

基于Python实现一个简单的HttpServer,当用户在浏览器中输入IP地址:8000时&#xff0c;则会返回index.html页面内容&#xff0c;访问其它信息&#xff0c;则会返回错误信息(404) """ httpserver v1.0 1.获取来自浏览器的请求&#xff0c; 2.判断如果请求内容是 …...

#循循渐进学51单片机#变量进阶与点阵LED#not.6

1、掌握变量的作用域及存储类别。 局部变量 函数内部声明的变量&#xff0c;只在函数内部有效&#xff0c;在本函数以外是不能使用的&#xff0c;叫局部变量。 全局变量 在函数外部声明的变量就是全局变量&#xff0c;一个源程序可以包含一个或多个函数&#xff0c;全局变量…...

访问者模式

图片转载自 #include<iostream> using namespace std; #include<list> /*模板工厂单例化&#xff0c;所有的商品被注册进工厂中*/ /*访问者模式&#xff08;行为型模式&#xff09; 访问者&#xff0c;被访问者 visit accept 让访问变成一种操作&#xff0c;不同…...

epoll 的实现

epoll 这么好&#xff0c;为什么迟至 2.6 版本的 kernel 才支持(epoll manual: The epoll API was introduced in Linux kernel 2.5.44.)&#xff1f;2.4 版本的 kernel 不支持 epoll&#xff1f; 原因很简单&#xff0c;epoll 没什么神奇的。在早期没有太多的并发连接要处理&…...

怎么用excel管理固定资产

在当今的数字时代&#xff0c;我们已经习惯了使用各种电子工具来提高我们的生产力。其中&#xff0c;Excel无疑是一个强大的工具&#xff0c;它不仅可以帮助我们处理数据&#xff0c;还可以用来进行复杂的计算和分析。然而&#xff0c;你可能不知道的是&#xff0c;Excel也可以…...

记录crack某IDE插件过程

声明&#xff1a;本文仅记录学习过程&#xff0c;已对关键位置脱敏处理&#xff0c;未提供任何工具&#xff0c;请支持正版。 反编译jar包 使用cfr进行对插件核心jar包MyBxxxxxx-obfuss.jar进行反编译&#xff0c;在本地生成a.txt。 java -jar cfr-0.152.jar MyBxxxx-obfuss.…...

Android DEX相关,ART加载OAT文件

android .dex文件,对于Android DEX文件详细说明 Android dex、odex、oat、vdex、art区别 Android下的DEX文件和SO文件梳理总结 Android[art]-Android dex&#xff0c;odex&#xff0c;oat&#xff0c;vdex&#xff0c;art文件结构学习总结 第四章 常见的 Android 文件格式&…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...