模式搜索简介 - 数据结构和算法教程

模式搜索简介 - 数据结构和算法教程

模式搜索是一种涉及搜索字符串、单词、图像等模式的算法。

我们使用某些算法来进行搜索过程。模式搜索的复杂性因算法而异。在数据库中执行搜索时它们非常有用。模式搜索算法对于在较大字符串的子字符串中查找模式非常有用。这个过程可以使用我们将在本文章中讨论的各种算法来完成。

模式搜索算法的特点:

  • 模式搜索算法应该快速准确地识别熟悉的模式。
  • 识别并分类不熟悉的模式。
  • 即使部分隐藏,也能识别模式。
  • 轻松、自动地快速识别模式。

朴素模式搜索算法

朴素模式搜索是其他模式搜索算法中最简单的方法。它检查模式中主字符串的所有字符。该算法对于较小的文本很有帮助。它不需要任何预处理阶段。我们可以通过检查一次字符串来找到子字符串。它也不占用额外的空间来执行操作。

朴素模式搜索方法的时间复杂度为 O(m*n)。m 是模式的大小,n 是主字符串的大小。

ini 复制代码
 // Naive Pattern 的 JS 程序
 // 搜索算法
 function search(pat, txt) 
 { 
     let M = pat.length; 
     let N = txt.length; 
     
     /* 逐个滑动 pat[] 的循环 */
     for (let i = 0; i <= N - M; i++) { 
         let j = 0; 
         
         /* 对于当前索引 i,检查是否匹配模式 */
         for (j = 0; j < M; j++) {
             if (txt[i + j] != pat[j]) {
         break; 
       }
         }   
         if (j == M) {// if pat[0...M-1] = txt[i, i+1, ...i+M-1] 
             console.log("Pattern found at index",i); 
     }
     } 
 } 
 ​
 let txt = "AABAACAADAABAAABAA"; 
 let pat = "AABA"; 
 search(pat, txt); 

输出:

复制代码
 在索引 0 处找到模式
 在索引 9 处找到模式
 在索引 13 处找到模式

时间复杂度: O(N*M) 辅助空间: O(1)

KMP算法

KMP算法用于在"文本"中查找"模式"。该算法从左到右逐个字符进行比较。但每当发生不匹配时,它都会使用一个名为"前缀表"的预处理表来跳过匹配时的字符比较。有时前缀表也称为LPS表。这里 LPS 代表"最长的正确前缀,也是后缀"。

如何使用 LPS 表

我们使用LPS表来决定当发生不匹配时要跳过多少个字符进行比较。 当发生不匹配时,检查模式中不匹配字符的前一个字符的 LPS 值。如果为"0",则开始将模式的第一个字符与下一个字符与文本中不匹配的字符进行比较。如果它不是"0",则开始将索引值等于前一个字符的LPS值的字符与模式中的不匹配字符与文本中的不匹配字符进行比较。

KMP算法示例

从左到右比较模式的第一个字符与文本的第一个字符

将模式的第一个字符与文本的下一个字符进行比较

比较模式0和模式1值

将模式0 与文本中的下一个字符进行比较。

将模式2 与文本中不匹配的字符进行比较。

KMP 算法的工作原理

让我们看一下 KMP 算法在文本中查找模式的工作示例。

脂多糖表

定义变量

比较 A 和 B

比较 A 和 C

比较 A 和 D

比较 A 与 A

将 B 与 B 进行比较

比较 C 和 D

比较 A 和 D

KMP算法的实现:

JavaScript

ini 复制代码
 // 在 pat[] 中出现 txt[] 的次数
 function computeLPSArray(pat, M, lps) 
 { 
 ​
     // 前一个最长前缀后缀的长度
     let len = 0; 
     lps[0] = 0; 
     // 循环计算 lps[i],其中 i 的取值范围为 1 到 M-1
     let i = 1; 
     while (i < M) { 
         if (pat[i] == pat[len]) { 
             len++; 
             lps[i] = len; 
             i++; 
         } 
         else // (pat[i] != pat[len]) 
         { 
         
             // This is tricky. Consider the example. 
             // AAACAAAA and i = 7. The idea is similar 
             // to search step. 
             if (len != 0) { 
                 len = lps[len - 1]; 
                 // 另外,请注意我们在这里不递增 i
             } 
             else // if (len == 0) 
             { 
                 lps[i] = 0; 
                 i++; 
             } 
         } 
     } 
 } 
 function KMPSearch(pat, txt) { 
     let M = pat.length; 
     let N = txt.length 
     
     // 创建一个lps[]数组,用于存储模式的最长前缀后缀值
     let lps = []; 
     
     // Preprocess the pattern (calculate lps[] array) 
     computeLPSArray(pat, M, lps); 
     let i = 0; // index for txt[] 
     let j = 0; // index for pat[] 
     while ((N - i) >= (M - j)) { 
         if (pat[j] == txt[i]) { 
             j++; 
             i++; 
         } 
         if (j == M) { 
             console.log("Found pattern at index:", i - j); 
             j = lps[j - 1]; 
         } 
         
         // mismatch after j matches 
         else if (i < N && pat[j] != txt[i]) 
         { 
         
             // 不要匹配 lps[0..lps[j-1]] 个字符,
             // 它们无论如何都会匹配
             if (j != 0) {
         j = lps[j - 1]; 
       } else {
         i = i + 1; 
       }
         } 
     } 
 } 
 ​
 // 为给定的模式pat[0..M-1]填充lps[]
 // 测试上述函数的驱动程序
 let txt = "ABABDABACDABABCABAB"; 
 let pat = "ABABCABAB"; 
 KMPSearch(pat, txt); 

输出

复制代码
 在索引 10 处找到模式

时间复杂度: O(n + m) 辅助空间: O(M)

相关推荐
wangruofeng1 小时前
AI Models 1.1.0 发布,查大模型价格、对比模型和找 API 地址
前端·aigc·ai编程
脚本自动化开发1 小时前
玩影之刃零,两张四千元级显卡怎么挑
后端
wangruofeng1 小时前
给前端开发者的 100 个设计参考网站
前端·设计
星栈4 小时前
视频即代码,Remotion 能做什么、不能做什么
前端·音视频开发
广州华水科技4 小时前
单北斗GNSS位移监测系统的应用与技术解析
前端
用户47949283569154 小时前
从一句话或代码仓到可交互 HTML:开源 Agent 画图技能 Archify v3.2 实测与选型边界
前端·后端·面试
努力的小雨5 小时前
别再复制日志给AI了!我让Codex自己去观测云查报错
后端
风骏时光牛马7 小时前
生成一个AI多模态标题,仅输出一条标题,无额外文字、问句、备选、配图、文案等任何附加内容,不需要其他的任务服务 只要标题。
前端
wangruofeng7 小时前
从 GIF 到 AVIF:网页图片格式演进与 2026 年选型指南
前端·架构
afumu7 小时前
Go 写一个只监听 127.0.0.1 的控制服务:鉴权、白名单、危险命令拦截
后端·安全·go