87. 扰乱字符串(动态规划图解)

2024-02-11 07:59

本文主要是介绍87. 扰乱字符串(动态规划图解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

69427e2554f0437e9c120f9fc3d94ae3.png

解题思路:

对于给定的两个字符串S和T。

如果S和T的长度不相等,T肯定不是S的扰乱字符串。

如果S和T的长度相等,则可以在某一个随机下标处进行分割,会将两个字符串S分割成两部分,同理,T也可以用两部分表示,如下如所示:

e55de795f57b4af4a389768df29029b1.png

字符串S被分割为S1和S2,字符串T被分割为T1和T2,此时可以分为两种情况:

  1. 情况一:S1和S2没有交换,此时需要判断T1是否是S1的扰乱字符串,T2是否是S2的扰乱字符串。
  2. 情况二:S1和S2交换了,此时需要判断T2是否是S1的扰乱字符串,T1是否是S1的扰乱字符串。

显然上述分割会将大问题分割成两个小问题:

  1. T1是否是S1的扰乱字符串,T2是否是S2的扰乱字符串
  2. T2是否是S1的扰乱字符串,T1是否是S2的扰乱字符串

子问题的解题步骤和大问题的解题步骤类似,显然可以使用动态规划来求解。

  1. 定义状态:dp[i][j][m][n],表示T[m,...,n]是否是S[i,... ,j]的扰乱字符串,因为如果是扰乱字符串,那个相同部分的长度一定相等,即 n - m = j - i = len,所以可以将四维数组优化为三维数组,d[i][j][len],表示字符串T中从j开始的len个字符串是否是从字符串S中 i 开始的len个字符串的扰乱字符串
  2. 状态转移方程:
    1. 假设随机划分处使得S1的长度为k,如下图所示:f60880da65cf490ea5abaec99872d06e.png
    2. 对于情况一,不交换S1和S2:ee26389346564264a83cc498ab9dbfba.png此时需要判断T1是否是S1的扰乱字符串,T2是否是S2的扰乱字符串,所以dp[i][j][len] = dp[i][j][k] && dp[i+k][j+k][len-k]
    3. 对于情况二,交换S1和S2:e115609c6482439c82a2f75cf372a9b0.png此时需要判断T2是否是S1的扰乱字符串,T1是否是S1的扰乱字符串,注意:需要令T2和S1的长度相等,T1和S2的长度相等,所以,dp[i][j][len] = dp[i][j+len-k][len] && dp[i+k][j][len-k]
    4. 上述只是判断了一处分割位置的状态转移方程,我们需要枚举出所有的分割位置,所以最终的状态转移方程为:dp[i][j][len] = ( dp[i][j][k] && dp[i+k][j+k][len-k] ) || ( dp[i][j+len-k][len] && dp[i+k][j][len-k] ),其中对于每一个len,k都需要从1枚举到 len-1,只要有一个枚举位置可以令 dp[i][j][len] 等于true即可,此时就可以结束枚举了。
  3. 初始状态:两个长度为1的字符串,显然如果这两个字符相等,则 dp[i][j][1] = true,否则false

AC代码:

class Solution {public static boolean isScramble(String s, String t) {int n = s.length();int m = t.length();if (n != m) {return false;}boolean[][][] dp = new boolean[n][n][n + 1];for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {dp[i][j][1] = s.charAt(i) == t.charAt(j);}}for (int len = 2; len <= n; len++) {//枚举s中的位置for (int i = 0; i <= n - len; i++) {//枚举t中的位置for (int j = 0; j <= n - len; j++) {//枚举分割的位置for (int k = 1; k <= len-1; k++) {//不交换S1和S2if(dp[i][j][k]&&dp[i+k][j+k][len-k]){dp[i][j][len]=true;break;}//交换S1和S2if (dp[i][j+len-k][k]&&dp[i+k][j][len-k]){dp[i][j][len]=true;break;}}}}}return dp[0][0][n];}
}

c747e8e96ae2457da43803873162d205.png

 

这篇关于87. 扰乱字符串(动态规划图解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/699280

相关文章

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

Python 字符串裁切与提取全面且实用的解决方案

《Python字符串裁切与提取全面且实用的解决方案》本文梳理了Python字符串处理方法,涵盖基础切片、split/partition分割、正则匹配及结构化数据解析(如BeautifulSoup、j... 目录python 字符串裁切与提取的完整指南 基础切片方法1. 使用切片操作符[start:end]2

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

浅谈MySQL的容量规划

《浅谈MySQL的容量规划》进行MySQL的容量规划是确保数据库能够在当前和未来的负载下顺利运行的重要步骤,容量规划包括评估当前资源使用情况、预测未来增长、调整配置和硬件资源等,感兴趣的可以了解一下... 目录一、评估当前资源使用情况1.1 磁盘空间使用1.2 内存使用1.3 CPU使用1.4 网络带宽二、

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

C# $字符串插值的使用

《C#$字符串插值的使用》本文介绍了C#中的字符串插值功能,详细介绍了使用$符号的实现方式,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录$ 字符使用方式创建内插字符串包含不同的数据类型控制内插表达式的格式控制内插表达式的对齐方式内插表达式中使用转义序列内插表达式中使用

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引