文章目录

  • HJ52 计算字符串的编辑距离
    • 描述
    • 输入描述
    • 输出描述
    • 示例1
  • HJ52 计算字符串的编辑距离
    • 描述
    • 输入描述
    • 输出描述
    • 示例1
    • 解题思路
      • 算法分析
      • 动态规划状态转移
      • 状态转移方程
      • 算法流程图
      • DP表格示例
      • 三种操作详解
      • 代码实现思路
      • 时间复杂度分析
      • 关键优化技巧
      • 实际应用场景
      • 算法扩展
      • 面试考点
    • 完整题解代码

HJ52 计算字符串的编辑距离

描述

Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转变成另一个所需的最少单字符编辑操作次数。被允许的转变包括:

  • 对于任意一个字符串,在任意位置插入一个字符;
  • 对于任意一个字符串,删除任意一个字符;
  • 对于任意一个字符串,替换任意一个字符。

现在,对于给定的字符串 s 和 t,请计算出它们的编辑距离。

输入描述

第一行输入一个长度为 1<=len(s)<=10^3,仅由小写字母组成的字符串 s。
第二行输入一个长度为 1<=len(t)<=10^3,仅由小写字母组成的字符串 t。

输出描述

输出一个整数,表示 s 和 t 的编辑距离。

示例1

输入:
abcdefg
abcdef

输出:
1

说明:
在这个样例中,可以选择将 s 末尾的 ‘g’ 删除。当然,也可以选择在 t 末尾插入 ‘g’。

HJ52 计算字符串的编辑距离

描述

Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转变成另一个所需的最少单字符编辑操作次数。被允许的转变包括:

  • 对于任意一个字符串,在任意位置插入一个字符;
  • 对于任意一个字符串,删除任意一个字符;
  • 对于任意一个字符串,替换任意一个字符。

现在,对于给定的字符串 s 和 t,请计算出它们的编辑距离。

输入描述

第一行输入一个长度为 1<=len(s)<=10^3,仅由小写字母组成的字符串 s。
第二行输入一个长度为 1<=len(t)<=10^3,仅由小写字母组成的字符串 t。

输出描述

输出一个整数,表示 s 和 t 的编辑距离。

示例1

输入:
abcdefg
abcdef

输出:
1

说明:
在这个样例中,可以选择将 s 末尾的 ‘g’ 删除。当然,也可以选择在 t 末尾插入 ‘g’。

解题思路

算法分析

这道题是经典的动态规划问题——编辑距离(Levenshtein距离)。主要涉及:

  1. 状态定义:dp[i][j]表示s[0:i]和t[0:j]的编辑距离
  2. 状态转移:根据字符是否相同选择最优操作
  3. 边界处理:空字符串的初始化
  4. 空间优化:滚动数组优化空间复杂度

动态规划状态转移

yes
no
dp_i_j
s_i_minus_1_eq_t_j_minus_1
dp_i_minus_1_j_minus_1
three_operations_min
delete dp_i_minus_1_j plus 1
insert dp_i_j_minus_1 plus 1
replace dp_i_minus_1_j_minus_1 plus 1
min_of_three

状态转移方程

graph LRA[状态转移方程] --> B[状态 dp_i_j]B --> C{当前字符是否相同}C -->|相同| D[继承左上状态 dp_i_减1_j_减1]C -->|不同| E[三种操作取最小值]E --> F[删除:删除 s_第_i_个字符]E --> G[插入:插入 t_第_j_个字符]E --> H[替换:将 s_第_i_个字符替换为 t_第_j_个]

算法流程图

flowchart TDA[读取字符串 s 和 t] --> B[获取长度:m 是 s 的长度,n 是 t 的长度]B --> C[创建 dp 数组,大小为 m 加 1 乘以 n 加 1]C --> D[初始化边界条件]D --> E[第 0 行:dp_0_j 设为 j,遍历所有 j]E --> F[第 0 列:dp_i_0 设为 i,遍历所有 i]F --> G[进入双重循环,填充 dp 表]G --> H{当前 s 的第 i 个字符是否等于 t 的第 j 个字符}H -->|是| I[dp_i_j 设为 dp_i_减1_j_减1]H -->|否| J[dp_i_j 设为三种操作中的最小值]I --> K{是否循环结束}J --> KK -->|否| GK -->|是| L[返回最终结果 dp_m_n]

DP表格示例

以s=“abc”, t="ab"为例:

graph TDA[DP 表格构建过程] --> B[构造完整 DP 数组并填充]B --> C[每个 dp_i_j 代表编辑距离]C --> D[完成后,查看 dp_3_2 的值]D --> E[最终答案:dp_3_2 等于 1]

三种操作详解

graph TDA[编辑操作] --> B[插入操作]A --> C[删除操作]A --> D[替换操作]B --> E[在字符串 s 中插入字符]B --> F[代价:dp_i_j减1 加一]C --> G[从字符串 s 中删除字符]C --> H[代价:dp_i减1_j 加一]D --> I[将 s 中字符替换为 t 中字符]D --> J[代价:dp_i减1_j减1 加一]

代码实现思路

  1. 基础DP版本

    • 二维数组存储所有状态
    • 时间复杂度O(mn),空间复杂度O(mn)
    • 易于理解和调试
  2. 空间优化版本

    • 滚动数组优化空间
    • 时间复杂度O(mn),空间复杂度O(min(m,n))
    • 适用于大规模数据
  3. 记忆化递归版本

    • 自顶向下的思考方式
    • 代码更直观,容易理解递归关系
    • 适合面试讲解

时间复杂度分析

算法版本时间复杂度空间复杂度特点
基础DPO(mn)O(mn)经典实现
空间优化O(mn)O(min(m,n))节省空间
记忆化递归O(mn)O(mn)易于理解

关键优化技巧

  1. 空间优化

    // 只需要两行数组
    prev := make([]int, m+1)
    curr := make([]int, m+1)
    
  2. 字符串长度优化

    // 确保s是较短的字符串
    if m > n {s, t = t, sm, n = n, m
    }
    
  3. 边界条件处理

    // 空字符串的初始化
    dp[0][j] = j  // 需要j次插入
    dp[i][0] = i  // 需要i次删除
    

实际应用场景

  1. 文本相似度计算:搜索引擎的模糊匹配
  2. 拼写检查:单词纠错功能
  3. DNA序列比对:生物信息学中的序列分析
  4. 版本控制:Git中的文件差异比较
  5. 自然语言处理:文本相似度度量

算法扩展

编辑距离扩展
加权编辑距离
最长公共子序列
最长公共子串
字符串匹配
不同操作不同代价
只允许插入删除
连续字符匹配
模式匹配算法

面试考点

  1. 状态定义能力:正确定义DP状态
  2. 状态转移推导:理解三种操作的含义
  3. 边界条件处理:空字符串的初始化
  4. 空间优化思维:滚动数组的使用
  5. 实际应用理解:算法的实际价值

这个问题是动态规划的经典应用,展示了如何将复杂问题分解为子问题,并通过状态转移方程求解最优解。编辑距离算法在实际工程中有广泛应用,是面试中的高频考点。

完整题解代码

package mainimport ("fmt"
)func main() {var s, t stringfmt.Scanln(&s)fmt.Scanln(&t)result := editDistance(s, t)fmt.Println(result)
}// editDistance 计算两个字符串的编辑距离
// 使用动态规划算法,时间复杂度O(mn),空间复杂度O(mn)
func editDistance(s, t string) int {m, n := len(s), len(t)// dp[i][j] 表示 s[0:i] 和 t[0:j] 的编辑距离dp := make([][]int, m+1)for i := range dp {dp[i] = make([]int, n+1)}// 初始化边界条件// s为空字符串时,需要插入t的所有字符for j := 0; j <= n; j++ {dp[0][j] = j}// t为空字符串时,需要删除s的所有字符for i := 0; i <= m; i++ {dp[i][0] = i}// 动态规划填表for i := 1; i <= m; i++ {for j := 1; j <= n; j++ {if s[i-1] == t[j-1] {// 字符相同,不需要操作dp[i][j] = dp[i-1][j-1]} else {// 字符不同,取三种操作的最小值dp[i][j] = min(dp[i-1][j]+1,   // 删除s[i-1]dp[i][j-1]+1,   // 插入t[j-1]dp[i-1][j-1]+1, // 替换s[i-1]为t[j-1])}}}return dp[m][n]
}// 空间优化版本:只使用O(min(m,n))空间
func editDistanceOptimized(s, t string) int {m, n := len(s), len(t)// 确保s是较短的字符串,优化空间使用if m > n {s, t = t, sm, n = n, m}// 只需要两行:当前行和上一行prev := make([]int, m+1)curr := make([]int, m+1)// 初始化第一行for i := 0; i <= m; i++ {prev[i] = i}// 逐行计算for j := 1; j <= n; j++ {curr[0] = j // 边界条件for i := 1; i <= m; i++ {if s[i-1] == t[j-1] {curr[i] = prev[i-1]} else {curr[i] = min(prev[i]+1,   // 删除curr[i-1]+1, // 插入prev[i-1]+1, // 替换)}}// 交换prev和currprev, curr = curr, prev}return prev[m]
}// 递归+记忆化版本(展示不同实现思路)
func editDistanceMemo(s, t string) int {m, n := len(s), len(t)memo := make([][]int, m+1)for i := range memo {memo[i] = make([]int, n+1)for j := range memo[i] {memo[i][j] = -1}}var dfs func(i, j int) intdfs = func(i, j int) int {// 边界条件if i == 0 {return j}if j == 0 {return i}// 记忆化if memo[i][j] != -1 {return memo[i][j]}if s[i-1] == t[j-1] {memo[i][j] = dfs(i-1, j-1)} else {memo[i][j] = min(dfs(i-1, j)+1,   // 删除dfs(i, j-1)+1,   // 插入dfs(i-1, j-1)+1, // 替换)}return memo[i][j]}return dfs(m, n)
}// min 返回三个数中的最小值
func min(a, b, c int) int {if a <= b && a <= c {return a}if b <= c {return b}return c
}// 用于两个数的min函数
func min2(a, b int) int {if a < b {return a}return b
}

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

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

相关文章

15.手动实现BatchNorm(BN)

15.1 BatchNorm操作手动实现 import torch from torch import nndef batch_norm(X,gamma,beta,moving_mean,moving_var,eps,momentum):if not torch.is_grad_enabled():#这个是推理模式X_hat(X-moving_mean)/torch.sqrt(moving_vareps)else:assert len(X.shape) in (2,4)if le…

【项目实践】SMBMS(Javaweb版)汇总版

文章目录前期准备工作数据库、数据表创建web项目创建项目文件目录配置Tomcat&#xff0c;导入依赖建立实体类编写基础公共方法类导入基础资源登录功能登录页面持久层dao层的用户登录及接口实现dao层接口实现所需的方法业务层sevice层的接口的实现接口实现相关的业务逻辑编写ser…

隐藏源IP的核心方案与高防实践

一、源IP暴露的风险 直接DDoS攻击&#xff1a;2025年Q2全球DDoS攻击峰值达3.8Tbps&#xff08;来源&#xff1a;Cloudflare报告&#xff09;漏洞利用&#xff1a;暴露的SSH端口平均每天遭受12,000暴力破解尝试数据泄露&#xff1a;直接连接数据库风险提升300% 二、4种有效隐藏方…

深度学习图像分类数据集—五种电器识别分类

该数据集为图像分类数据集&#xff0c;适用于ResNet、VGG等卷积神经网络&#xff0c;SENet、CBAM等注意力机制相关算法&#xff0c;Vision Transformer等Transformer相关算法。 数据集信息介绍&#xff1a;五种电器识别分类&#xff1a;[notebook, phone, powerbank, tablet, w…

Windows11家庭版配置frigate 嵌入自研算法(基于Yolov8)-【2】

使用 YOLOv8 的 results.xyxy 结构&#xff0c;下面是一个完整的 MQTT 推送脚本&#xff0c;用于把识别到的目标&#xff08;比如突涌水、水渍、障碍物等&#xff09;发送到 Frigate 的 MQTT 接口。✅ 前提假设 YOLOv8 推理代码已经运行并生成 results.xyxy。每一行是 [x1, y1,…

安装llama-factory报错 error: subprocess-exited-with-error

报错信息如下 Using cached https://mirrors.aliyun.com/pypi/packages/17/89/940a509ee7e9449f0c877fa984b37b7cc485546035cc67bbc353f2ac20f3/av-15.0.0.tar.gz (3.8 MB)Preparing metadata (pyproject.toml) ... errorerror: subprocess-exited-with-error Preparing metad…

QT 多线程 管理串口

记录一下自己使用多线程进行串口管理和数据读取的过程。如果有问题的话可以发消息给我。背景在使用QT制作一个串口数据读取处理的小软件的时候&#xff0c;发现了存在界面卡顿的情况&#xff0c;感觉性能太低&#xff0c;于是考虑把串口数据的读取和处理都放到子线程的缓冲区中…

在虚拟环境中复现论文(环境配置)

前提&#xff1a;已经下载condawinR&#xff0c;输入cmd进入命令行conda create -n PPT python3.8.3 pytorch1.7.0conda create -n PPT(虚拟环境名) python3.8.3(包名) pytorch1.7.0(包名)安装完毕&#xff0c;激活虚拟环境&#xff1a;conda activate PPT根据论文readme要求安…

Flutter Web 的发展历程:Dart、Flutter 与 WasmGC

Flutter Web 应该是 Flutter 开发者里最不“受宠”的平台了&#xff0c;但是其实 Flutter 和 Dart 团队对于 Web 的投入一直没有减少&#xff0c;这也和 Flutter 还有 Dart 的"出生"有关系&#xff0c;今天就借着 Dart 团队的 mer Ağacan 和 Martin Kustermann 在油…

c#方法关键字,ref、out、int

在 C# 中&#xff0c;ref、out 和 in 是用于方法参数传递的关键字&#xff0c;它们控制参数如何在方法和调用者之间传递数据。以下是对这三个关键字的详细分析&#xff1a;1. ref 关键字&#xff08;引用传递&#xff09;作用允许方法修改调用者的变量&#xff1a;通过引用传递…

设计模式—初识设计模式

1.设计模式经典面试题分析几个常见的设计模式对应的面试题。1.1原型设计模式1.使用UML类图画出原型模式核心角色&#xff08;意思就是使用会考察使用UML画出设计模式中关键角色和关系图等&#xff09;2.原型设计模式的深拷贝和浅拷贝是什么&#xff0c;写出深拷贝的两种方式的源…

深度学习-参数初始化、损失函数

A、参数初始化参数初始化对模型的训练速度、收敛性以及最终的性能产生重要影响。它可以尽量避免梯度消失和梯度爆炸的情况。一、固定值初始化在神经网络训练开始时&#xff0c;将权重或偏置初始化为常数。但这种方法在实际操作中并不常见。1.1全零初始化将所有的权重参数初始化…

格密码--Ring-SIS和Ring-LWE

1. 多项式环&#xff08;Polynomial Rings&#xff09; 设 f∈Z[x]f \in \mathbb{Z}[x]f∈Z[x] 是首一多项式&#xff08;最高次项系数为1&#xff09; 则环 RZ[x]/(f)R \mathbb{Z}[x]/(f)RZ[x]/(f) 元素为&#xff1a;所有次数 <deg⁡(f)< \deg(f)<deg(f) 的多项式…

前端工作需要和哪些人打交道?

前端工作中需要协作的角色及协作要点 前端工作中需要协作的角色及协作要点 前端开发处于产品实现的 “中间环节”,既要将设计方案转化为可交互的界面,又要与后端对接数据,还需配合团队推进项目进度。日常工作中,需要频繁对接的角色包括以下几类,每类协作都有其核心目标和…

万字长文解析 OneCode3.0 AI创新设计

一、研究概述与背景 1.1 研究背景与意义 在 AI 技术重塑软件开发的浪潮中&#xff0c;低代码平台正经历从 “可视化编程” 到 “意图驱动开发” 的根本性转变。这种变革不仅提升了开发效率&#xff0c;更重新定义了人与系统的交互方式。作为国内领先的低代码平台&#xff0c;On…

重学前端006 --- 响应式网页设计 CSS 弹性盒子

文章目录盒模型一、盒模型的基本概念二、两种盒模型的对比 举例三、总结Flexbox 弹性盒子布局一、Flexbox 的核心概念​​二、Flexbox 的基本语法​​​​1. 定义 Flex 容器​​​2. Flex 容器的主要属性​​​​3. Flex 项目的主要属性​​​​三、Flexbox 的常见布局示例​​…

rLLM:用于LLM Agent RL后训练的创新框架

rLLM&#xff1a;用于LLM Agent RL后训练的创新框架 本文介绍了rLLM&#xff0c;一个用于语言智能体后训练的可扩展框架。它能让用户轻松构建自定义智能体与环境&#xff0c;通过强化学习进行训练并部署。文中还展示了用其训练的DeepSWE等智能体的出色表现&#xff0c;以及rLL…

rocky8 --Elasticsearch+Logstash+Filebeat+Kibana部署【7.1.1版本】

软件说明&#xff1a; 所有软件包下载地址&#xff1a;Past Releases of Elastic Stack Software | Elastic 打开页面后选择对应的组件及版本即可&#xff01; 所有软件包名称如下&#xff1a; 架构拓扑&#xff1a; 集群模式&#xff1a; 单机模式 架构规划&#xff1a…

【JVM】内存分配与回收原则

在 Java 开发中&#xff0c;自动内存管理是 JVM 的核心能力之一&#xff0c;而内存分配与回收的策略直接影响程序的性能和稳定性。本文将详细解析 JVM 的内存分配机制、对象回收规则以及背后的设计思想&#xff0c;帮助开发者更好地理解 JVM 的 "自动化" 内存管理逻辑…

Qt获取hid设备信息

Qt 中通过 HID&#xff08;Human Interface Device&#xff09;接口获取指定的 USB 设备&#xff0c;并读取其数据。资源文件中包含了 hidapi.h、hidapi.dll 和 hidapi.lib。通过这些文件&#xff0c;您可以在 Qt 项目中实现对 USB 设备的 HID 接口调用。#include <QObject&…