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

4.2_1朴素模式匹配算法

知识总览:

什么是字符串的模式匹配:

主串:想从该串获取结果的串

模式串:想搜索的内容,不一定在主串中能搜到,子串一定能在主串中搜到

字符串模式匹配:在主串找模式串并返回找到的第一个模式串所在位置

 朴素模式匹配算法:

暴力匹配,从主串选取跟模式串长度一样的子串去跟模式串对比,俩串相等返回首字符下标,俩串不相等继续找,直到找到为止返回首字符下标或者找完也找不到为止。

实现方法1:Index()函数定位操作

跟上一节找主串的子串函数一样

注意目前的串都是用的静态数组且是数组第一个字符位置不适用的形式,即数组存储字符的下标跟字符位序相同,且找模式串可寻找的次数为n-m+1(n为主串,m为模式串)

实现方法2:不用Index()函数定位,使用指针

 第一轮:

设置2个扫描指针,分别扫描主串和模式串,指针指到哪则2个串的字符比较到哪,开始i和j分别指向主串S和模式串T的下标为1的第一个字符,分别为a和a即相等,则俩指针后移指向下标为2的第2个字符,都为b继续后移,来指针都指向第3个字符a都相等,继续后移指向第4个字符a相等,继续后移指向第5个字符都为b相等,继续后移此时俩指针都指向第6个字符,i指向主串S的a,j指向模式串的T的c,则俩字符不相等,指向主串的指针i回到指向下一个子串的第一个位置,即主串S的第2个字符位置,指向模式串的指针j回到模式串的第一个位置

i=i-j+2;//即此时i=6,j=6,下一轮i=i-j+2=2

//俩指向字符不相等时,j当前的值表示匹配到了子串的第几个字符,i-j就可以让i的值回到目前这个子串的前边一个位置,i和j都是统一往前移的,因为指针i要指向下一个子串的第一个位置,所以要在此基础上+2,如下图现在j指向了当前子串的第6个字符,i=6,j=6,i=i-j=0即i回到了这个子串的前边一个位置(注意是当前子串的前边一个位置,不是当前子串的第一个位置,这意味着要指向下一个子串的第一个位置要+2,因为+1就又指向当前子串的第一个位置了),然后还要刨除这个子串的第一个位置指向下一个字串的第一个位置,则要i=i+2=2

j=1;//即此时j=6,下一轮j=1,j指向模式串起始位置

第2轮: 

i的值恢复为2即i==2,j的值恢复为1即j==1,俩指针指向的值为b和a不相等,即i指向的当前子串和模式串不相等,则i=i-j=2-1=1即i回到当前子串b的前一个位置,i=i+2=3为指向下一个子串的第一个位置,指向模式串T的指针j回到模式串第一个位置即j==1

i=i-j+2;//即此时i=2,j=1,下一轮i=i-j+2=2-1+2=3

j=1;//即此时j=6,下一轮j=1,j指向模式串起始位置

 

第3轮:

上同,i从第3个字符开始的子串和j=1开始的模式串比较,每当发现i和j所指的字符相同的时候,让i和j分别+1,当i==4,j==2时不相等,i回到下一个子串的第一个位置,j回到起始位置

i=i-j+2;//即此时i=4,j=2,下一轮i=i-j+2=4-2+2=4

j=1;//即此时j=2,下一轮j=1,j指向模式串起始位置

 

第4轮:

每当发现i和j所指的字符相同的时候,让i和j分别+1,当j所指的位置超出了模式串的长度,就说明匹配成功,则返回当前子串的第一个字符位置即让i-j即可,注意没有+1,因为在匹配成功的时候i和j都已经往前移动了1个位置,所以当i-j的时候其实指向的位置为当前子串的第一个字符位置

 

代码版:

2个指针i和j,i指向主串,j指向模式串,初始值都为1即指向主串和模式串的第一个字符,如下while循环

if(S.ch[i]==T.ch[j]); ++i;++j;即当前2个指针指向的字符相等,让i和j都+1

i=i-j+2;j=1;即当前2个指针指向的字符不相等则让i回到下一个子串的第一个字符位置,j回到模式串第1个位置

return i-T.length;如果匹配成功,则说明j>T.length,已跳出while循环

return 0;;即匹配失败,即i已经把整个主串走了一遍,即在走到主串的最后一个字符时,不相等,i的下一轮下标为S.length+1(我怎么感觉S.length要比实际的字符个数多1个,因为S数组中存储的第一个位置没有存元素啊,比说最后一个字符index=3,实际S.length=4吧,那下一个位置i不就是4吗,那这个while循环不是还能走一遍吗,但是走的话if第一个语句就数组下标越界了吧。。。。。。。。。。。。。。。。)

 

最坏时间复杂度:

假如有如下长度为n的主串,长度为m的模式串,子串和模式串匹配的时候每次只有最后一个字符不相等,且主串n只有在最后一个m长度的子串中才和模式串匹配,即要总共匹配n-m+1次,每次都要匹配m个长度,则时间开销为(n-m+1)m=nm-m²+m,即时间开销为O(nm),因为一般n>>m,所以把m²舍去

 

 知识回顾:

。。。。。。。。。。。。。。。 

http://www.lryc.cn/news/575775.html

相关文章:

  • Webshell工具的流量特征分析(菜刀,蚁剑,冰蝎,哥斯拉)
  • LeetCode 2302.统计得分小于K的子数组数目
  • 力扣第45题-跳跃游戏2
  • [mcp-servers] docs | AI客户端-MCP服务器-AI 架构
  • linux cp与mv那个更可靠
  • 浅析阿拉伯语OCR技术的核心难点及其应用场景
  • LeetCode 2311.小于等于 K 的最长二进制子序列:贪心(先选0再选1)-好像还是比灵神写的清晰些
  • 996引擎-假人系统
  • VUE3入门很简单(3)--- watch
  • 重塑音视频叙事:Premiere文本剪辑与Podcast AI降噪的革命性工作流
  • 解决 “docker-compose: command not found“ 错误
  • C2远控篇CC++SC转换格式UUID标识MAC物理IPV4地址减少熵值
  • Selenium+Pytest自动化测试框架实战
  • 玄机抽奖Spring Web项目
  • MySQL5.7和8.0 破解root密码
  • 【软件测试】银行信贷项目-面试题常问整理
  • Python 中 `for` 循环与 `while` 循环的实际应用区别:实例解析
  • 事件循环(Event Loop)机制对比:Node.js vs 浏览器​
  • 【UniApp 日期选择器实现与样式优化实践】
  • WinAppDriver 自动化测试:C#篇
  • 第七章:总结
  • linux环境内存满php-fpm
  • WebRTC(十):RTP和SRTP
  • 七天学会SpringCloud分布式微服务——03——Nacos远程调用
  • LightGBM:极速梯度提升机——结构化数据建模的终极武器
  • 2.1、STM32 CAN外设简介
  • 鸿蒙实时音视频流处理框架开发实战——基于HarmonyOS 4.0与分布式软总线的低延时高可靠架构
  • Miniconda+Jupyter+PyCharm初始环境配置
  • Java全栈面试实录:从电商平台到AIGC,技术栈深度解析
  • Linux驱动学习day8(按键驱动读取方式、GPIO、pinctrl子系统)