大话数据结构--串的匹配算法

简介: 大话数据结构--串的匹配算法

前言


废话不多,数据结构必须学! 每天更新一章,一篇写不完的话会分成两篇来写~

资料获取

image.png


朴素的模式匹配算法


在文章(相当于一个大串)中找到单词的定位,这种子串的定位操作通常称做串的模式匹配

这是串中很重要的操作之一


实例


我们要找到主串S=“wyjbat”中,找到T = “bat”这个子串的位置。通常要进行下面的步骤。

1.主串S第一位开始,S与T字母进行匹配

image.png

2.多次比较从4位开始,S与T,3个字母全匹配,匹配成功

image.png


简单的说,就是对主串的每一个字符作为子串开头,与要匹配的字符串进行匹配。对主串做大循环,每个字符开头做T的长度的小循环,直到匹配成功或全部遍历完成为止。

这个算法也太低效了,不玩!!


5.6 KMP模式匹配算法


什么是KMP?


三个科学家D.E.Knuth、 J.H.Morris 和V.R.Pratt,以他们的姓氏命名的


为什么要用KMP算法?


因为暴力匹配效率太低

比如我们要在主串中匹配子串ABCD,这很简单对吧,常规的思路就是一位一位的匹配(这个思路就是暴力匹配算法)

image-20211116093132194

image.png

如果对不上了,我们让子串往后移动

image.png

上面这种思路可以用代码来实现

/**
  * 暴力破解法
  * @param ts 主串
  * @param ps 模式串
  * @return 如果找到,返回在主串中第一个字符出现的下标,否则为-1
  */
 public static int bf(String ts, String ps) {
     char[] t = ts.toCharArray();
     char[] p = ps.toCharArray();
     int i = 0; // 主串的位置
     int j = 0; // 模式串的位置
     while (i < t.length && j < p.length) {
        if (t[i] == p[j]) { // 当两个字符相同,就比较下一个
            i++;
            j++;
        } else {
            i = i - j + 1; // 一旦不匹配,i后退
            j = 0; // j归0
        }
     }
     if (j == p.length) {
        return i - j;
     } else {
        return -1;
     }
 }

上面的程序没问题,只能说不够好!

主串匹配失败的位置除了第一个A之外再也没有A了,我们为什么知道主串前面只有一个A?因为前三个已经匹配过了啊!它们都是匹配的。

我们可以这样保存i不动,移动j

image.png

KMP算法的思想就是利用已经部分匹配的有效信息,保持i指针不回溯,通过修改j指针,让子串尽量的移动到有效的位置!

再详细的可以观看这篇文章,写的很好!

我就不更了,日后在更

(原创)详解KMP算法 - 孤~影 - 博客园 (cnblogs.com)


KMP模式匹配算法实现


/*通过计算返回子串T的next数组。*/
 ?void get_ next ( String T, int *next )
 {
     int i,j;
     i=1;
     j=0;
     next[1]=0;
     while ( i<T[0]) /*此处T[0]表示串T的长度*/
     {
     if (j==0 11 T[i]== T[j]) /* T[i]表示后缀的单个字符,*/
                             /* T[j]表示前缀的单个字符*/
     {
         ++i;
         ++j;
         next[i]=j;
     }
     else
     j= next[j]; /*若字符不相同,则j值回溯*/
     }     
 }


/*返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。*/
 /* T非空,1SposSStrLength (s)。*/
 int Index KMP (String s, String T, int pos )
 {
     int i= pos;/*i用于主串S当前位置下标值,若pos不为1, */
                 /*则从pos位置开始匹配*/
     int j= 1;   /*j用于子串T中当前位置下标值*/
     int next[255] ; /*定义一next数组*/
     get_ next(T, next); /*对串工作分析,得到next数组*/
     while(i<= S[0] &j<= T[0]) /*若i小于S的长度且j小于T的长度时,*/
                             /*循环继续*/
     {
         if (j==0日1 S[i]== T[j]) /*两字母相等则继续,与朴素算法增加了*/
                                 /*j=0判断*/
         ++i;
         ++j;
         else    /*指针后退重新开始匹配★/
     {
         j = next[j];    /* j退回合适的位置,i值不变*/
     }
     if(j > T[0] )
         return i-T[0] ;
     else
         return 0;
 }


5.7总结


串是由零个或多个字符组成的有限序列,又名字符串。本质上是一种线性表的扩展,相对于线性表关注一个个元素来说,串这种结构更多的是关注它子串的应用问题,如查找、替换等操作。现在的高级语言都有针对串的函数可以调用,我们在使用这些函数的时候,同时也应该要理解它当中的原理,以便于再碰到复杂问题时,可以更灵活的使用



相关文章
|
2天前
|
机器学习/深度学习 存储 算法
数据结构与算法 动态规划(启发式搜索、遗传算法、强化学习待完善)
数据结构与算法 动态规划(启发式搜索、遗传算法、强化学习待完善)
9 1
|
6天前
|
搜索推荐 C语言
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
11 0
|
6天前
|
存储 算法
Leetcode 30天高效刷数据结构和算法 Day1 两数之和 —— 无序数组
给定一个无序整数数组和目标值,找出数组中和为目标值的两个数的下标。要求不重复且可按任意顺序返回。示例:输入nums = [2,7,11,15], target = 9,输出[0,1]。暴力解法时间复杂度O(n²),优化解法利用哈希表实现,时间复杂度O(n)。
17 0
|
12天前
|
存储 机器学习/深度学习 算法
|
16天前
|
存储 算法 Python
程序设计的艺术:算法与数据结构的魅力
程序设计的艺术:算法与数据结构的魅力
8 0
|
17天前
|
存储 算法
数据结构开篇(普普通通浅浅聊数据结构)什么是数据结构 、什么是算法、重要性、如何学好数据结构呢
数据结构开篇(普普通通浅浅聊数据结构)什么是数据结构 、什么是算法、重要性、如何学好数据结构呢
|
24天前
|
存储 人工智能 算法
有哪些数据结构与算法是程序员必须要掌握的?——“数据结构与算法”
有哪些数据结构与算法是程序员必须要掌握的?——“数据结构与算法”
|
26天前
|
存储 算法 Serverless
数据结构期末复习(六)查找算法
数据结构期末复习(六)查找算法
11 0
|
26天前
|
存储 人工智能 算法
数据结构期末复习(1)数据结构和算法 线性表
数据结构期末复习(1)数据结构和算法 线性表
16 0
|
26天前
|
存储 算法 搜索推荐
浙江大学数据结构陈越 第一讲 数据结构和算法
浙江大学数据结构陈越 第一讲 数据结构和算法
48 1