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

贵阳工程建设招聘信息网站asp网站开发好怎么预览

贵阳工程建设招聘信息网站,asp网站开发好怎么预览,合肥快速建站在线咨询,百度推广开户多少钱深入理解 KMP 算法:高效字符串匹配的利器 一、KMP 算法的由来及其解决的问题 在计算机科学领域,字符串处理是一项极为常见且基础的任务。其中,字符串匹配问题更是频繁出现,例如在文本编辑器中查找特定单词、在生物信息学中搜索 D…

深入理解 KMP 算法:高效字符串匹配的利器

一、KMP 算法的由来及其解决的问题

  在计算机科学领域,字符串处理是一项极为常见且基础的任务。其中,字符串匹配问题更是频繁出现,例如在文本编辑器中查找特定单词、在生物信息学中搜索 DNA 序列模式等。早期,人们普遍采用朴素的字符串匹配算法,该算法简单直观,但在面对长字符串时效率低下。正是在这样的背景下,1977 年,Donald E. Knuth、Vaughan Pratt 和 James H. Morris 共同提出了 KMP 算法,旨在更高效地解决字符串匹配问题,从此开启了字符串匹配算法优化的新篇章。
  KMP 算法主要解决的是在一个主字符串(text)中查找一个模式字符串(pattern)出现的位置。简单来说,给定一个长度为 n 的主字符串 text 和一个长度为 m 的模式字符串 pattern(其中 m <= n),需要找出 pattern 在 text 中首次出现的起始索引。朴素字符串匹配算法的时间复杂度为 O (n * m),在最坏情况下,对于每个主字符串中的字符位置,都需要对模式字符串进行完整匹配,导致大量不必要的重复比较。而 KMP 算法通过巧妙利用已经匹配的部分信息,避免了重复匹配,将时间复杂度降低到 O (n + m),大大提高了字符串匹配的效率。下面我们来介绍 KMP 算法的流程。

二、算法流程

2.1 前缀表

  前缀表记录了模式字符串中每个前缀子串的最长相等前缀和后缀的长度。对于模式字符串 pattern,设其长度为 m,前缀表是一个长度为 m 的数组,记为 next。next[i] 表示 pattern 的前 i + 1 个字符组成的子串中,最长相等前缀和后缀的长度(不包括整个子串本身)。例如,对于模式字符串 “aabaaf”,其前缀表为 [0, 1, 0, 1, 2, 0]。当 i = 0 时,子串为 “a”,没有相等的前缀和后缀,所以 next[0] = 0;当 i = 1 时,子串为 “aa”,有相等的前缀和后缀"a",next[1] = 0;当 i = 2 时,子串为 “aab”,没有相等的前后缀,所以 next[2] = 0;同理,当 i = 3 时,子串为"aaba",所以 next[3] = 1;当 i = 4时,next[4] = 2;当 i = 5 时,next[5] = 0。

  • 构建过程
    • 初始化:设模式字符串 pattern 的长度为 m,创建一个长度为 m 的数组 next,初始时 next[0] = 0,因为单个字符没有前后缀。
    • 遍历计算:设两个指针,i 指向后缀末尾(从1开始),j 指向前缀末尾(初始为0)。在遍历过程中,比较 pattern[i] 和 pattern[j]。
      • 如果 pattern[i] == pattern[j],说明找到了一个更长的相等前缀和后缀,j 增加 1,然后将 j 赋值给 next[i],即 next[i] = j,同时 i 也增加 1,继续下一个位置的计算。
      • 如果 pattern[i] != pattern[j],且 j > 0,说明当前位置无法形成更长的相等前缀和后缀,此时需要回溯 j,令 j = next[j - 1],继续比较 pattern[i] 和 pattern[j]。这是因为之前已经知道了长度为 j - 1 的前缀的最长相等前缀和后缀长度,通过回溯可以尝试找到一个更短的前缀,使得 pattern[i] 能够与该前缀的下一个字符匹配。
      • 如果 pattern [i] != pattern [j] 且 j == 0,说明从开头到当前位置 i 都没有相等的前缀和后缀,此时 next[i] = 0,i 增加 1,继续下一个位置的计算。

2.2 字符串匹配过程

  • 匹配开始:设主字符串 text 的长度为 n,模式字符串 pattern 的长度为 m。初始化两个指针,i 用于遍历主字符串 text(从 0 开始),j 用于遍历模式字符串 pattern(从 0 开始)。
  • 字符比较:在匹配过程中,不断比较 text [i] 和 pattern [j]。
    • 如果 text[i] == pattern[j],说明当前字符匹配成功,i 和 j 都增加 1,继续比较下一个字符。
    • 如果 text[i] != pattern[j],此时不能简单地将 i 回溯到上次匹配的起始位置重新开始比较,而是要利用前缀表进行优化。令 j = next[j - 1],这意味着将模式字符串向右移动,使得已经匹配的部分尽可能多地利用之前的匹配信息,减少不必要的重复比较。
  • 匹配成功或失败判断:当 j 等于模式字符串的长度 m 时,说明模式字符串在主字符串中找到了匹配,返回当前 i - j 的值,即为模式字符串在主字符串中首次出现的起始索引。如果 i 遍历完主字符串 text,j 仍未达到 m,说明模式字符串在主字符串中不存在匹配,返回 -1。

三、举个栗子

假设主字符串 text = “abababca”,模式字符串 pattern = “ababca”。

3.1 构建前缀表

  1. 初始化 next 数组,长度为 6,next[0] = 0,并令 j = 0。
  2. 当 i = 1 时,pattern[1] = ‘b’,pattern[0] = ‘a’,不相等,next[1] = 0。
  3. 当 i = 2 时,pattern[2] = ‘a’,pattern[0] = ‘a’,相等,j 从 0 变为 1,next[2] = 1。
  4. 当 i = 3 时,pattern[3] = ‘b’,pattern[1] = ‘b’,相等,j 从 1 变为 2,next[3] = 2。
  5. 当 i = 4 时,pattern[4] = ‘c’,pattern[2] = ‘a’,不相等,j 回溯,j = next[2 - 1] = next[1] = 0。因为pattern[4]与pattern[0]不相等,所以next[4] = 0。
  6. 当 i = 5 时,pattern[5] = ‘a’,pattern[0] = ‘a’,相等,j 从 0 变为 1,next[5] = 1。所以前缀表next = [0, 0, 1, 2, 0, 1]。

3.2 字符串匹配过程

  1. 初始化 i = 0,j = 0。
  2. 比较 text[0] 和 pattern[0],都为 ‘a’,匹配成功,i = 1,j = 1。
  3. 比较 text[1] 和 pattern[1],都为 ‘b’,匹配成功,i = 2,j = 2。
  4. 比较 text[2] 和 pattern[2],都为 ‘a’,匹配成功,i = 3,j = 3。
  5. 比较 text[3] 和 pattern[3],都为 ‘b’,匹配成功,i = 4,j = 4。
  6. 比较 text[4] 和 pattern[4],text[4]为’a’,pattern[4]为’c’,不匹配,j 回溯,j = next[4 - 1] = next[3] = 2。
  7. 继续比较 text[4] 和 pattern[2],text[4]为’a’,pattern[2]为’a’,匹配成功,i = 5,j = 3。
  8. 比较 text[5] 和 pattern[3],text[5]为’b’,pattern[3]为’b’,匹配成功,i = 6,j = 4。
  9. 比较 text[6] 和 pattern[4],text[6]为’c’,pattern[4]为’c’,匹配成功,i = 7,j = 5。
  10. 比较 text[7] 和 pattern[5],text[7]为’a’,pattern[5]为’a’,匹配成功,j 达到模式字符串长度 m = 6,此时返回 i - j + 1 = 7 - 6 + 1 = 2,说明模式字符串在主字符串中首次出现的起始索引为 2。

四、代码实现

class Solution {public int match(String text, String pattern) {if (pattern.length() == 0) return 0;int[] next = new int[pattern.length()];getNext(next, pattern);int j = 0;for (int i = 0; i < text.length(); i++) {while (j > 0 && pattern.charAt(j) != text.charAt(i)) j = next[j - 1];if (pattern.charAt(j) == text.charAt(i)) j++;if (j == pattern.length()) return i - pattern.length() + 1;}return -1;}private void getNext(int[] next, String s) {int j = 0;next[0] = 0;for (int i = 1; i < s.length(); i++) {while (j > 0 && s.charAt(j) != s.charAt(i)) j = next[j - 1];if (s.charAt(j) == s.charAt(i)) j++;next[i] = j; }}
}
http://www.dtcms.com/a/452033.html

相关文章:

  • 璧山职教中心示范校建设网站网站图片设置软件
  • 前端做网站的兼职如何看网站做没做推广
  • 手机怎么制作网站教程视频我想用c 来做网站
  • 公司建设网站申请国外有哪些设计网站推荐
  • 网站与微信结合为什么网站建设还要续费
  • 公司网站服务类型怎么填php网站分类目录程序 网址导航程序 织梦二次开发
  • 打开网站自动弹出qqwordpress做多语言
  • 做流量网站有收入吗国外常用的网站开发系统
  • 怎么下载网站的模板云南昆明做网站
  • 江苏建设厅网站首页湖北网站设计制作开发
  • 现在做网站还赚钱吗在线网页制作网站
  • 个人做企业 网站公司网站找哪家
  • 什么查网站是否降权那个相亲网站做的比较好
  • 建设网站制flash xml网站
  • 网站设计知名企业在百度做广告多少钱
  • python网站搭建广州做手机网站建设
  • 音乐网站建设规划书汕头网站建设设计价格
  • 瓷器网站怎么做win2003搭建php网站
  • html5在线网站nas可以做网站吗
  • 北京网站备案在哪污水处理厂网站建设
  • 建网站需什么条件个人免费建站系统
  • 合肥建站推广贴吧推广400一个月
  • 网站开发文案模板icp备案号怎么填写
  • 做视频采集网站犯法网页主题设计思路及制作步骤
  • 看手机的网站做网站获取手机号码
  • 旅游网站开发系统郑州网站建设 云极
  • 公司网站改版要怎么做广告联盟平台排名
  • seo网站建设接单温州网页设计美工招聘
  • app网站开发流程图开发一个网站系统报价
  • 莆田高端网站建设做网站推广托管费用