栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

(七)数据结构-串

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

(七)数据结构-串

一、串的定义和实现

字符串简称串,计算机在非数值处理的对象基本都是字符串数据

1.1串的定义

串(string)是由零个或多个字符组成的有序序列,一般记为S=‘a1a2a3…an’(n>=10)
其中S是串名,单括号括起来的字符序列是串的值;
ai可以是字母、数字或者其他字符;
串中字符的个数n称为串的长度;
当n=0时的串称为空串;

1.2子串、主串

串中任意多个连续的字符组成的子序列称为该串的子串
包含子串的串称为主串

1.2.1串中的位置

注意:由一个或多个空格(空格是特殊字符)组成的串称为空格串
(注意:空格串不是空串)并且空格串的长度为串中空格字符的个数

  • 某个字符在串中的序号称为该字符在串中的位置
  • 子串在主串中的位置以子串的第一个字符在主串的位置来表示
    当两个串的长度相等且对应位置的字符都相等的时候,称这两个串是相等的

串的模式匹配算法包括:朴素模式匹配算法(暴力匹配方法)、KMP算法

二、串的朴素模式匹配算法(暴力匹配方法)

子串的定位操作通常称为串的模式匹配,它是求子串(通常称为模式串)在主串中的位置。
算法思想:

  1. 主串长度n,模式串长度m
  2. 它是将主串中所有长度为m的子串与模式串对比
  3. 直到找到第一个与模式串完全匹配的子串,并返回子串起始位置,若所有的子串都不匹配,则返回0
    (最多对比n-m+1个子串)

若当前子串匹配失败,则主串指针i指向下一个子串的第一个位置i=i-j+2(主串指针回溯)
模式串指针j回到模式串的第一个位置
最坏时间复杂度为(nm)

三、KMP算法

KMP算法就是想要利用已经匹配的信息来提高搜索的效率,且为了不发生不必要的回溯

KMP的时间复杂度O(n+m)
求next数组的时间复杂度为O(m)
模式匹配过程最坏时间复杂度O(n)

根据图片为例,当用朴素匹配算法的时候,匹配到位置6的时候,主串和模式串的出现了不匹配的情况,但是位置1-5是对应的,(不匹配的字符之前,一定是和模式串一致的)为了不发生不必要的回溯,我们可以将朴素模式匹配算法进行改进,改进后的算法称为kmp算法

当匹配到第六个元素出现匹配失败的时候:

  1. 匹配到了j=6发现不匹配的时候,可以得知j=1~5时,主串和模式串一定是对应的,所以就没有必要用朴素匹配模式的时候

  2. 依次将指针往后挪i=2,j=1,发现不匹配

  3. 再继续将指针往后挪i=3,j=1,发现i=3==j=1,但是i=4不等于j=2,发现不匹配

  4. 再继续将指针往后挪i=4,j=1,发现i=4j=1,i=5j=2,此时对i=6是否能够匹配未知,那么我们可以令主串指针i不变,模式串指针j=3

    当匹配到第五个元素出现匹配失败的时候:

  5. 匹配到了j=5时不匹配的时候,可以得知j=1~4时,主串和模式串一定是对应的,所以就没有必要用朴素匹配模式的时候

  6. 依次将指针往后挪i=2,j=1,发现不匹配

  7. 再继续将指针往后挪i=3,j=1,发现i=3==j=1,但是i=4不等于j=2,发现不匹配

  8. 再继续将指针往后挪i=4,j=1,发现i=4==j=1,此时对i=5是否能够匹配未知,那么我们可以令主串指针i不变,模式串指针j=2

当匹配到第1个元素出现匹配失败的时候:

  1. 我们尝试匹配下一个相邻子串,那么在代码角度我们可以让j=0
    那么此次改进的模式串指针如下:(并且这个改进的模式串只适用于该模式串’abaabc’)

    那么我们可以用next数组将这个结果存起来,表明当我们在某个位置发生失配的时候,我们将j值修改为多少
    第一个位置比较特殊,不仅要把j修改为0,还需要将i++和j++
    (next数组的长度只与模式串相关,与主串无关)

三、KMP算法优化(nextval数组) 3.1nextval数组的由来
  • 假设模式串匹配到i=3出现匹配失败的时候,那么我们从next数组中我们可以将此时j=3挪到j=1,但是挪到j=1还是出现a,可以知道j=1和j=3都是匹配失败,所以我们完全可以让j=0,因为若j=1的话,我们可以知道是注定匹配失败的,所以最好的情况是直接让next3等于0

  • 假设模式串匹配到j=5的时候出现匹配失败,那么此时从next数组可以知道将j=5挪到j=2,虽然我们不知道此时i=5的字符是什么,但是我们可以确定的是肯定不是b,所以让j=2这个匹配操作肯定也是失败的,那么此时我们应该将j=1开始匹配
  • 所以与多了一步,我们不如修改next[5]的值=1

    此时我们只优化了next数组,我们将进行优化得到nextval
3.1手算nextval数组

我们首先算出next数组,再由next数组求nextval数组
nextval[0]=0:我们无脑写0
nextval[2]=0: 此时j=3的值是a,next[2]=1指向j=1,发现j=3的值与j=1的值相等,那么我们就将nextval[3]的值等于next[1]中的nextval的值

nextval[6]=4: 此时j=6的值是a,next[6]=4指向j=4,发现j=6的值与j=4的值不相等,那么我们就将nextval[6]的值等于自己的next[6]

3.1手算next数组

next数组的作用:当模式串的第j个字符失配的时,从模式串的第next[j]继续往后匹配
任何模式串都一样,第一个字符不匹配时,只能匹配下一个字符,因此以后的都写为next[1]=0

任何模式串都一样,第一个字符不匹配时,只能匹配下一个字符,因此以后的都写为next[2]=1

next[4]:我们首先让模式串一步一步往右移动,无法匹配接着一直移动


直到整个模式串跨越了整个分界线,接下来我们应该对比的是i和j所指的元素,因此我们让j的指针直接指向j=1

next[5]:我们首先让模式串一步一步往右移动,无法匹配接着一直移动,此时匹配上了,那么我们可以让j=2

例子:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1026606.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号