算法:动态规划之字符串模式匹配

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

一、问题描述

二、常规算法

三、动态规划算法

总结


提示:以下是本篇文章正文内容,下面案例可供参考

一、问题描述

给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配

'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。

两个字符串完全匹配才算匹配成功。

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

输入:
s = "aa"
p = "*"
输出: true
解释: '*' 可以匹配任意字符串。

输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。

输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce"。

输入:
s = "acdcb"
p = "a*c?b"
输出: false

二、常规算法

解题思路:

我们将这个题拆解一下,分为不包含*的场景和包含*的场景

1、不包含*的场景,我们逐位进行比对即可得出最终的结论

2、包含*的场景,我们无法确定起点位置,所以我们用s的每一个字符,去和p的每一个字符进行匹配,记录匹配的结果,最终相当于成了一道寻路题了,只不过限制了前进方向为向下或者向右,起点从首个字符能匹配到的地方开始算起。

代码示例:

public void test() {String s = "acdcb";String p = "a*c?b";// 模式匹配串中不包含*if (!p.contains("*")) {if (s.length() != p.length()) {System.out.println(false);return;}for (int i = 0; i < s.length(); i++) {if (p.charAt(i) == '?' || s.charAt(i) == p.charAt(i)) {continue;}System.out.println(false);return;}System.out.println(false);return;}// 模式匹配串中包含*, 我们用s中的每一个字符都去和p中的每个字符匹配, 结果保存在一个二维数组中, s中有几个字符, 就有几行数据int[][] array = new int[s.length()][p.length()];for (int i = 0; i < s.length(); i++) {for (int j = 0; j < p.length(); j++) {if (p.charAt(j) == '?' || p.charAt(j) == '*' || s.charAt(i) == p.charAt(j)) {// 单个字符匹配, 标记为1array[i][j] = 1;continue;}// 单个字符不匹配, 标记为0array[i][j] = 0;}}// 最后我们得到一个全部标记了0或1的二维数组, 起点是第一行中的某个元素, 要求从这个元素开始向下或者向右移动, 最终能抵达斜对角的位置for (int j = 0; j < p.length(); j++) {if (array[0][j] == 1) {boolean can = canReach(array, 0, j);if (!can) {continue;}System.out.println(true);return;}}
}public boolean canReach(int[][] array, int row, int col) {// 如果当前位置已经到达右下角对角线,返回trueif (row == array.length - 1 && col == array[0].length - 1) {return true;}// 如果当前位置超出矩阵范围或者元素为0,返回falseif (row >= array.length || col >= array[0].length || array[row][col] == 0) {return false;}// 递归向下或向右移动return canReach(array, row + 1, col) || canReach(array, row, col + 1);
}

常规算法,胜于更易理解,将复杂问题拆解为简单的子问题,逐个破解。 

三、动态规划算法

解题思路:

最终的匹配结果依赖于最后一个字符的匹配结果,最后一个字符的匹配结果又依赖于前一个字符的匹配结果,依此类推,直至首个字符匹配成功。那么前一个字符的匹配结果在该字符的匹配结果的什么位置呢,答案是上方或者左侧。由于p中包含*字符,这个*可能代表0 ~ N个字符,所以可能是跳过该位置,有可能是跨了多个位置。我们约定横跨是向右,跳过是向下。

所以当出现p中某位是*时,它取的结果来自它的上方和左侧,如果有一个是通过,本位置即为通过。

代码示例: 

public void test() {String s = "aa";String p = "a";// 初始化动态规划数组boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];// 当模式串为空时,只有当字符串也为空时才匹配成功dp[0][0] = true;// 处理模式串中的第一个字符for (int j = 1; j <= p.length(); j++) {if (p.charAt(j - 1) == '*') {dp[0][j] = dp[0][j - 1];}}// 动态规划过程for (int i = 1; i <= s.length(); i++) {for (int j = 1; j <= p.length(); j++) {if (p.charAt(j - 1) == '?' || s.charAt(i - 1) == p.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1];} else if (p.charAt(j - 1) == '*') {dp[i][j] = dp[i - 1][j] || dp[i][j - 1];}}}System.out.println(JSON.toJSONString(dp));// 返回最终匹配结果System.out.println(dp[s.length()][p.length()]);
}

 动态规划算法,要找一下规律,代码比较简洁。


总结

解题过程已奉上,快快练起来,简单到有手就行!

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

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

相关文章

uni-app中轮播图实现大图预览

参考效果 当轮播图滑动切换的时候更新自定义下标&#xff0c;当图片被点击的时候大图预览。 参考代码 商品详情页轮播图交互 <script setup lang"ts"> // 轮播图变化时 const currentIndex ref(0) const onChange: UniHelper.SwiperOnChange (ev) > …

MPEG4Extractor

1、readMetaData 必须要找到 Moov box&#xff0c;找到 Mdat box或者 Moof box&#xff0c;并且创建了 ItemTable 大端 box 分为 box header 和 box content&#xff1a; box header由8个字节组成&#xff0c;前面四个字节表示这个box 的大小&#xff08;包含这个头的8字节&a…

PCL 格网法计算点云的占地面积

目录 一、算法原理二、代码实现三、结果展示四、测试数据本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT生成的文章。 一、算法原理 该方法主要用于粗略统计机载点云的占地面积。方法原理是将点云沿 X O Y XOY

【深度学习】SDXL tensorRT 推理,Stable Diffusion 转onnx,转TensorRT

文章目录 sdxl 转 diffusers转onnx转TensorRT sdxl 转 diffusers def convert_sdxl_to_diffusers(pretrained_ckpt_path, output_diffusers_path):import osos.environ["HF_ENDPOINT"] "https://hf-mirror.com" # 设置 HF 镜像源&#xff08;国内用户使…

长期使用外接键盘,外物压着自带键盘,容易导致华硕飞行堡垒FX53VD键盘全部失灵【除电源键】

华硕飞行堡垒FX53VD键盘全部失灵【除电源键】 前言一、故障排查二、发现问题三、使用方法总结 前言 版本型号&#xff1a; 型号 ASUS FX53VD&#xff08;华硕-飞行堡垒&#xff09; 板号&#xff1a;GL553VD 故障情况描述&#xff1a; 键盘无法使用&#xff0c;键盘除开机键外…

大学生如何当一个程序员——第三篇:热门专业学习之路6

文章出自https://www.bjsxt.com/xiulian.html#1F 各位小伙伴想要博客相关资料的话关注公众号&#xff1a;chuanyeTry即可领取相关资料&#xff01; 大数据和云计算学习 1.大数据学习之前“必看”2.Hadoop框架3.数据仓库技术4.Spark内存计算框架5.机器学习和数据挖掘6.Storm流式…

深入浅出:原生态App封装的艺术

一、原生态App封装的优势 性能的极致&#xff1a;原生App直接调用设备的硬件资源&#xff0c;减少了中间层的干扰&#xff0c;从而实现更快的运行速度和更流畅的动画效果。 2. 用户体验的完美&#xff1a;原生App可以访问并遵循特定平台的设计指南&#xff0c;提供与操作系统无…

TWS降噪耳机船运模式驱动实现

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送蓝牙音频,DSP音频项目核心开发资料, 驱动实现 Ship mode=SM SM-GND 接充电盒激活,退出船运模式, 船运模式单独做一个模块。 XB6035 芯片相当于一个电子开关…

开发分销商城小程序app,轻松助你业绩倍增

开发分销商城小程序app&#xff0c;轻松助你业绩倍增&#xff01; 1. 一键分享&#xff0c;业务拓展&#xff1a;分销商城小程序可生成独特的分销链接与二维码&#xff0c;让你的分销员分享给亲朋好友、社交媒体粉丝。迅速扩大销售网络&#xff0c;提升产品知名度。 2. 佣金管…

口碑公认好的洗地机有哪些?行业公认口碑洗地机

随着扫地机、洗地机等智能清洁家电的不断坚固&#xff0c;近年来洗地机成为备受欢迎的智能家电产品。这些洗地机不仅在家居清洁方面发挥了有效作用&#xff0c;而且大大节省了开支节省了时间成本。只需手持操控&#xff0c;就能在下班后轻松进行清洁&#xff0c;使清洁体验变得…

Maven之属性管理

1.属性管理 1.1 属性配置与使用 ①&#xff1a;定义属性 <!--定义自定义属性--> <properties><spring.version>5.2.10.RELEASE</spring.version> </properties>②&#xff1a;引用属性 <dependency><groupId>org.springframewor…

ssh终端登录后不自动执行 .bashrc

问题描述 ssh终端登录后不自动执行.bashrc 解决方案 确认SHELL类型 在终端输入&#xff1a; echo $SHELL确认SHELL类型为/bin/bash 确认.bash_profile文件 输入&#xff1a; vi ~/.bash_profile确认是否存在以下内容&#xff1a; if [ -f ~/.bashrc ]; then. ~/.bashr…

Mysql 重要知识点1(含面试题1)

Mysql 知识点较多&#xff0c;这里涵盖了基本知识点&#xff0c;包括SQL语句 、重要面试题等。后面还有几章Mysql的知识点&#xff0c;分别是刷题总结与进阶优化SQL 面试题等。 目录 Mysql 安装Mysql 重要知识点SQL 重要语句面试题精选 Mysql 安装 1.官网下载mysql5.7版本压缩…

C++突破栈区内存限制(堆区)

栈区的内存空间一般是在windows上1M-2M 堆区64位&#xff0c;windows10一般是1G-2G

1. Mybatis 中 SqlSession接口的三种实现

Mybatis 中 SqlSession接口的三种实现 ​SqlSession​ 是一个接口&#xff0c;并且里面包含了许多 CRUD 操作数据库等方法。 ​SqlSession​​ 它有三个实现类&#xff0c;分别是 SqlSessionManager​​ 、DefaultSqlSession​​ 和 SqlSessionTemplate​​&#xff0c;其中 …

日志服务管理和inode号

一、系统日志管理 1.1系统日志的介绍 在现实生活中&#xff0c;记录日志也非常重要&#xff0c;比如银行的转账记录&#xff0c;飞机上的黑盒子&#xff0c;那么将系统和应用发生的事件记录至日志中&#xff0c;以助于排错和分析使用 日志记录的内容包括&#xff1a; 历史事…

Vue路由 - 工作原理(深入理解)

目标: 了解hash改变, 如何显示不同的组件的过程 1.基本思路: 用户点击了页面上的a链接 导致了 URL 地址栏中的 Hash 值发生了变化 前端js监听了到 Hash 地址的变化 前端js把当前 Hash 地址对应的组件渲染都浏览器中 2.实现简单的前端路由: 1.src/views/创建并在App.vue里…

springboot学生综合测评系统源码和论文

随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;学生综合测评系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;学校规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#xff0c;而…

scanf函数和printf函数

1.scanf函数 int scanf ( const char * format, ... );函数功能&#xff1a; 从键盘读取数据如果读取成功&#xff0c;返回读取到的数据个数如果读取失败&#xff0c;返回EOF 不常见的读取格式&#xff1a; %md -->读取m个宽度的数据 int main() {int n 0;scanf("%4d&…

Java里的实用类

1.枚举 语法&#xff1a; public enum 变量名{ 值一&#xff0c;值二} 某个变量的取值范围只能是有限个数的值时&#xff0c;就可以把这个变量定义成枚举类型。 2…装箱&#xff08;boxing&#xff09; 和拆箱&#xff08;unboxing&#xff09; 装箱&#xff08;boxing&…