字符串编辑距离

2023-05-16

    字符串的编辑距离,又称为Levenshtein距离。是利用字符操作,把字符串A转换成字符串B所需要的最少操作数。其中,字符操作包括:

  • 删除一个字符
  • 插入一个字符
  • 修改一个字符

    例如对于"hello"和"hell",可以通过插入一个'o'和删除一个'o'来达到目的。

    一般来说,两个字符的编辑距离越小,则它们越相似。如果两个字符串相同,则它们的编辑距离为0.可以分析出,两个字符串的编辑距离肯定不超过它们的最大长度(可以通过先把短串的每一位都修改成长串对应位置的字符,然后插入长串中的剩下字符。)

问题描述:

    给定两个字符串A和B,求字符串A至少经过多少步字符操作变成字符串B。

问题分析:

(1)首先考虑A串的第一个字符

    假设存在两个字符串A和B,长度分别为lenA和lenB。首先考虑第一个字符,如果是一样的,所以只需要计算A[2……lenA]和B[2……lenB]之间的距离即可。那么如果两个字符串的第一个字符不一样的话,那么要考虑把第一个字符变成一样的:

  • 修改A串的第一个字符成B串的第一个字符,之后只需要计算A[2……lenA]和B[2……lenB]之间的距离即可;
  • 删除A串的第一个字符,之后只需要计算A[2……lenA]和B[1……lenB]之间的距离即可;
  • 把B串的第一个字符插入到A串的第一个字符之前,之后仅需要计算A[1……lenA]和B[2……lenB]的距离即可。

(2)接下来只需要考虑A串的第i个字符和B串的第j个字符。

    这个时候我们不考虑A的前i-1个字符和B的第j-1个字符。如果A串的第i个字符和B的第j个字符相等,即A[i]=B[j],则只需要计算A[i+1……lenA]和B[j+1……lenB]之间的距离即可。如果不想等,则:

  • 修改A的第i个字符为B的第j个字符,之后仅需要计算A[i+1……lenA]和B[j+1……lenB]之间的距离即可;
  • 删除A的第i个字符,之后只需要计算A[i+1……lenA]和B[j……lenB]之间的距离即可;
  • 把B串的第j个字符插入到A串的第i个字符之前,之后仅需要计算A[i.....lenA]和B[j+1......lenB]之间的距离即可。

构建动态规划方程:

用dp[i][j]表示A串从第i个字符开始和B串第j个字符开始的距离。则从上面的分析,不难推导出动态规划方法:

dp[i][j]=\left\{\begin{matrix} 0 & i=0,j=0 \\ j & i=0,j>0 \\ i & i>0,j=0 \\ min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+flag)&i>0,j>0 \end{matrix}\right.

flag\left\{\begin{matrix} 0& A[i]=B[j]\\ 1& A[i]!=B[j] \end{matrix}\right.

代码如下:

public class 字符串编辑距离 {
	public static int editDistance(String source,String target){
		int len1=source.length();
		int len2=target.length();
		//第一个字符串的长度为i的子串到第二个字符串的长度为j的子串的编辑距离
		int[][] dp=new int[len1][len2];
		for(int i=0;i>len1;i++){
			dp[i][0]=i;
		}
		for(int j=0;j<len2;j++){
			dp[0][j]=j;
		}
		for(int i=1;i<len1;i++){
			for(int j=1;j<len2;j++){
				int addOp=dp[i][j-1]+1;
				int delOp=dp[i-1][j]+1;
				int changeOp=dp[i-1][j-1]+(source.charAt(i-1)==target.charAt(j-1)?0:1);
				dp[i][j]=Math.min(Math.min(addOp, delOp), changeOp);
			}
		}
		return dp[len1-1][len2-1];
	}
	
	public static void main(String[] args){
		String source="sailn";
		String target="failing";
		System.out.println(editDistance(source, target));
	}

}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串编辑距离 的相关文章

  • 8.16 线程池;HTTP;数据库索引

    1 讲一下TCP连接 xff0c 三次握手四次挥手 https blog csdn net hellodake article details 81080415 网路的七层协议是什么 xff1f 物理层 xff0c 数据链路层 xff0c
  • 二分快速幂

    题目描述 xff1a 给定一个double类型的浮点数base和int类型的整数exponent 求base的exponent次方 思路 xff1a 把指数转化为二进制 xff0c 比如8 11 61 8 8 8 1 8 0 11 61 1
  • Spring原理+配置详解

    IOC xff1a inverse of control反转控制 负责创建对象 xff0c 管理对象 xff08 通过依赖注入 xff09 xff0c 配置对象 xff0c 并且管理这些对象的生命周期 以前对象的创建是由开发人员自己维护 x
  • JAVA线程sleep()和wait()区别

    sleep是Thread类的静态方法 xff0c 所以它不能改变对象的锁 xff1b wait是Object的方法 xff1b sleep是会让线程暂停工作一段时间 xff0c 休眠一段时间 xff0c 让出CPU的使用 xff0c 但是不
  • 在idea 中 修改项目结构

    在IDEA 中创建的项目往往我们需要修改一些目录的结构类型 xff0c 正常呢有两种方式 xff01 整理如下 xff1a 一 这种最简单 直接使用 鼠标右键完成 1 在你想要改变结构的目录上 鼠标右键 2 选择 Mark director
  • 数组中重复的数字|||数组中只出现一次的数

    1 找出数组中重复的数字 题目描述 xff1a 在一个长度为n的数组里的所有数字都在0 n 1的范围内 数组中某些数字是重复的 xff0c 但不知道有几个数字重复了 xff0c 也不知道每个数字重复了几次 请找出数组中任意一个重复的数字 例
  • spring aop思想

    spring插件 xff1a STS插件 spring整合junit测试 每一个方法都不需要先获得容器再获得对象了 帮我们创建容器 64 RunWith SpringJUnit4ClassRunner class 指定创建容器时使用哪个配置
  • 线程池种类以及参数设置问题

    JDK1 5中引入了强大的concurrent包 xff0c 线程池的实现ThreadPoolExcutor 线程池种类 通常开发者都是利用Executors提供的通用线程池创建方法 xff0c 去创建不同配置的线程池 xff0c 主要区别
  • 乐观锁、悲观锁,实现一个乐观锁

    悲观锁 总是假设最坏的情况 xff0c 每次去拿数据的时候都认为别人会修改 xff0c 所以每次在拿数据的时候都会上锁 xff0c 这样别人想拿这个数据就会阻塞直到它拿到锁 传统的关系型数据库里边就用到了很多这种锁机制 xff0c 比如行锁
  • 优化查询的方法

    1 使用索引 应尽量避免全表扫描 xff0c 首先应考虑在where及order by xff0c group by涉及的列上建立索引 2 优化SQL语句 3 优化数据库对象 优化表的数据类型对表进行拆分使用中间表来提高查询速度 4 硬件优
  • 【远景能源】截取字符串

    截取字符串 package 远景能源 import java util Scanner public class 截取字符串2 public static void main String args Scanner sc 61 new Sc
  • JVM内存模型以及栈溢出、堆溢出

    JVM内存模型 线程共享 xff1a 堆 方法区 线程私有 xff1a 虚拟机栈 本地方法栈 程序计数器 堆 xff1a 存放所有对象实例 xff1b 方法区 xff1a 存储已被虚拟机加载的类信息 xff0c 常量 静态变量 xff0c
  • 线程和进程的区别

    线程和进程的区别 xff1a 调度 xff1a 线程作为调度和分配的基本单位 xff0c 进程是拥有资源的基本单位 xff1b 并发性 xff1a 不仅进程之间可以并发执行 xff0c 同一个进程的不同线程之间也可以并发执行 xff1b 拥
  • Spring容器应用到项目

    1 管理Service对象和DAO对象 2 Listener xff1a 监听器 xff08 监听属性创建销毁 xff09 xff0c 监听器中方便获得事件源 管理容器在项目中的生命周期 配置Listener来管理ApplicationCo
  • 使用注解配置spring

    为主配置文件引入新的命名空间 xff08 context约束 xff09 xff1b 开启使用注解代理配置文件 xff1b 在类中使用注解完成配置 xff1b 自动装配有缺点 xff1a 如果匹配到多个类型一致的对象 xff0c 将无法选择
  • ArchLinux安装全过程

    文章目录 安装桌面软件美化 arch很美好 xff0c 不多说直接开搞 xff0c 记录我的安装过程并解决问题 安装 1 镜像下载 清华大学开源镜像站 xff1a TUNA 2 虚拟机加载 选择 Arch Lnuxarchiso x86 6
  • spring bean的生命周期

    Spring Bean的完整生命周期从创建Spring容器开始 xff0c 直到最终Spring容器销毁Bean 一个Bean从创建到销毁 xff0c 如果是用BeanFactory来生成 管理Bean的话 xff0c 会经历以下几个阶段
  • 线程的状态总结以及各状态之间转换

    1 初始 xff08 NEW xff09 xff1a 新创建了一个线程对象 xff0c 但还没有调用start xff08 xff09 方法 xff1b 实现Runnable接口和继承Thread类可以得到一个线程类 xff0c new一个
  • HTTP和HTTPS

    HTTPS就是HTTP加上加密处理 xff08 一般是SSL安全通信线路 xff09 43 认证 43 完整性保护 HTTPS的作用 xff1a 内容加密 xff1a 建立一个信息安全通道 xff0c 来保证数据传输的安全 xff1b 身份
  • spring整合JDBC+spring aop事务

    1 spring整合JDBC spring中提供了一个可以操作数据库的对象 xff0c 对象封装了JDBC技术 JDBCTemplate xff1a JDBC模板对象 与DBUtils中的QueryRunner非常相似 JDBCDaoSup

随机推荐

  • 网站高并发&高可用处理

    1 三大问题 高并发 xff1a 多个进程或线程同时访问同一资源会产生并发问题 xff1b 高可用大数据量 2 解决方案 初级解决方案 xff1a 系统或服务器级别的解决方案 xff1a 增大服务器的CPU xff1b 增加内存条 xff1
  • 背包问题详解

    1 0 1背包问题 问题描述 xff1a 有N件物品和一个容量为V的背包 第i件物品的重量是w i xff0c 价值是p i 求解将哪些物品装入背包可使这些物品的总重量不超过背包容量 xff0c 且价值总和最大 思路 xff1a 每种物品仅
  • 堆排序原理与实现

    堆排序实际上是利用堆的性质来进行排序的 xff0c 我们通常说的堆就是二叉堆 xff0c 二叉堆又称完全二叉树或者近似完全二叉树 堆排序是选择排序的一种 可以利用数组的特点快速定位指定索引的元素 数组可以根据索引直接获取元素 xff0c 时
  • Hashmap1.7和1.8区别+ConcurrentHashmap1.7和1.8区别

    Hashmap JDK1 7中 使用一个Entry数组来存储数据 xff0c 用key的hashcode取模来决定key会被放到数组里的位置 xff0c 如果hashcode相同 xff0c 或者hashcode取模后的结果相同 xff0c
  • TOP k问题

    题目 xff1a 有1千万条短信 xff0c 有重复 xff0c 以文本文件的形式保存 xff0c 一行一条 xff0c 有重复 请用5分钟时间 xff0c 找出重复出现最多的前10条 解析 xff1a 对于本题来说 xff0c 某些面试者
  • CAS操作是怎么实现的

    CAS是compare and swap xff0c 翻译过来就是比较并交换 维护三个变量值 xff0c 一个是内存值V xff0c 一个是期望的旧的值A xff0c 一个是要更新的值B 更新一个变量的时候 xff0c 只有当预期值A与内存
  • liunx在整合springboot 项目时出现错误CLUSTERDOWN The cluster is down

    在运行springboot项目并且把项目利用二级缓存 xff0c 储存到集群中时候在idea下报错显示CLUSTERDOWN The cluster is down 可以进入linux中查看集群配置 连接到某个节点此时显示此时节点明显显示的
  • volatile关键字

    java提供了一种稍弱的同步机制 xff0c volatile变量 xff0c 用来确保将变量的更新操作通知到其他线程 当把变量声明为volatile类型的时候 xff0c 编译器与运行时都会注意到这个变量是共享的 xff0c 所以不会将该
  • MVCC

    在并发读写数据库时 xff0c 读操作可能会不一致的数据 xff08 脏读 xff09 为了避免这种情况 xff0c 需要实现数据库的并发访问控制 xff0c 最简单的方式就是加锁访问 由于加锁会将读写操作串行化 xff0c 所以不会出现不
  • AQS理解

    AbstractQueuedSynchronizer简称AQS xff0c 是一个用于构建锁和同步容器的框架 事实上concurrent包内许多类都是基于AQS构建 xff0c 例如ReentrantLock Semaphere Count
  • B树、B+树及索引

    B树 xff1a 每个节点都存储key和data xff0c 所有节点组成这棵树 xff0c 并且叶子节点指针为null B 43 树 xff1a 只有叶子节点存储data xff0c 叶子节点包含了这棵树的所有键值 xff0c 叶子节点不
  • Arrays.sort和Collections.sort实现原理解析

    Collections sort方法底层就是调用的Arrays sort方法 写一个例子看源码 xff1a public static void main String args List lt String gt strings 61 A
  • Java代理模式之动态代理

    代理模式是设计模式中非常重要的一种类型 代理模式从类型上来说 xff0c 可以分为静态代理和动态代理两种类型 假设一个场景 xff0c 有一个蛋糕店 xff0c 卖的蛋糕都是用蛋糕机做的 xff0c 而且不同种类的蛋糕由不同的蛋糕机来做 x
  • 二叉树镜像

    求二叉树镜像 public class Solution public void Mirror TreeNode root if root 61 61 null return if root left 61 61 null amp amp
  • 设计模式之适配器模式

    适配器模式是作为两个不兼容的接口之间的桥梁 这种类型的设计模式属于结构型模式 xff0c 它结合了两个独立接口的功能 这种模式涉及到一个单一的类 xff0c 该类负责加入独立的或不兼容的接口功能 举个真实的例子 xff0c 读卡器是作为内存
  • 设计模式之单例模式

    1 懒汉式 xff0c 线程不安全 public class Demo1 private static Demo1 instance private Demo1 public static Demo1 getInstance if inst
  • Lambda表达式详解

    Java 8最值得学习的特性就是Lambda表达式 Lambda写的好可以极大减少代码冗余 xff0c 同时可读性也好过冗长的内部类 xff0c 匿名类 举例说明一下 xff1a xff08 1 xff09 创建线程传统写法 xff1a T
  • Android8.0以上实现APP(应用)开机自启动

    一 程序中实现APP开机自启动 可参考 xff1a https www cnblogs com jetereting p 4572302 html 二 设置APP开机自启动权限 小米手机设置开机启动应用权限 xff08 Android9 0
  • 跳台阶问题

    1 输出斐波那契数列的第n项 直接上代码 xff1a public class Fibonacci public static int fibonacci int n if n 61 61 0 return 0 if n 61 61 1 r
  • 字符串编辑距离

    字符串的编辑距离 xff0c 又称为Levenshtein距离 是利用字符操作 xff0c 把字符串A转换成字符串B所需要的最少操作数 其中 xff0c 字符操作包括 xff1a 删除一个字符插入一个字符修改一个字符 例如对于 34 hel