数据结构基础知识点二

文章介绍了串的基本概念,包括串的定义、长度和子串,强调串是一种特殊线性表。讨论了串的存储结构,如静态数组、动态数组和链式存储。重点讲述了串的模式匹配,尤其是朴素模式匹配算法和KMP算法,解释了KMP算法如何优化匹配过程,通过部分匹配值减少不必要的回溯。
摘要由CSDN通过智能技术生成

三、串

  1.串的定义和操作
  字符串(string),S=‘a1a2a3…an’ (n>=0) 串的位序从1开始而不是从0开始  S是串名  单引号括起来的字符序列是串的值  ai可以是字母、数字或其他字符  串中字符个数n称为串的长度  n=0时的串为空串  空格也是字符
  串是一种特殊的线性表,与一般线性表不同之处在于它的数据对象限定为字符集,增删改查通常以字串为操作对象。
  串中任意多个连续的字符组成的子序列称为该串的子串,相应地,包含字串的串称为主串
  串的比较:比较字符对应的二进制数的大小
  串的定位:返回字串自第一个字符的位置 没有找到字串返回0
  字符集编码:一个字符和二进制的对应规则,英文字符 采用ASCII字符集,中英字符采用Unicode字符集 (utf-8或utf-16),常见乱码问题

  2.串的存储结构
  (1)定长顺序存储表示即静态数组,超出预定义长度的串值会被舍弃,截断掉。串长两种表示方法:一是用额外变量len存放串的长度;二是加一个不计入串长的结束标记字符“\0”,此时的串长为隐含值。(2)堆分配存储表示即动态数组;(3)块链存储表示即链式存储,每个节点一个字符(存储密度低,字符1B,指针4B)或多个字符(存储密度高)。
  串的操作:串赋值StrAssign、串比较StrCompare、求串长StrLength、串联接Concat、求子串SubString五种操作构成串类型的最小操作子集,由这些操作可组成其他串操作。

  3.串的模式匹配
  子串的定位操作称为串的模式匹配,求的是模式串(子串)在主串中的位置,主串中未必存在模式串。
  简单模式匹配算法(朴素模式匹配算法):从主串S(n个字符)的第一个字符起,与模式串T(m个字符)的第一个字符比较,相等则继续逐个比较后续字符,不相等则从主串的下一个字符起,重新和模式串的字符比较。  最坏时间复杂度为O(nm)。 最好情况时,匹配失败O(n-m+1)即主串的每个子串的第一个字符就和模式串不匹配;匹配成功O(m)即主串的第一个子串就和模式串完全匹配。
  KMP算法:在简单模式匹配算法中,存在主串指针向前走m步,回退m-1步这样的最坏情况,模式串也不断在回退,导致算法的时间复杂度很高。让主串不回溯,每轮比较只回退模式串的指针,这样的算法就是KMP算法。kmp算法的时间复杂度为O(n+m)仅在主串与子串有很多“部分匹配”时才显得比简单模式匹配算法快得多,一般情况下简单模式匹配算法实际执行时间近似为O(n+m)。
  部分匹配值(Partial Match,PM)为字符串前缀和后缀的最长相等前后缀长度。
  移动位数=已匹配的字符数-对应的部分匹配值。
  Move=(j-1)-PM[j-1]  => Move=(j-1)-next[j] => 将子串的比较指针j回退的位置 j=next[j]+1
  将字符串的PM表右移一位,即得到字符串的next数组。为使公式更加简洁、计算简单,通常将next数组整体+1。
  next[0]=空,next[1]=0,next[2]=1。
求next值代码实现:

//i 游标,遍历T
void get_next(char T[], int next[])
{
	int i = 1;
	next[1] = 0;//恒为零
	int j = 0;
	while (i < T[0])//T[0]中记录了字符串的长度
	{
		if (j == 0 || T[i] == T[j])//j==0,说明再次回到了开头
		{
			++i; ++j;
			next[i] = j;//记录出现重复的次数
		}
		else {
			j = next[j];//不相同,找个位置重新比较
		}
	}
}

  KMP算法的进一步优化:用nextval数组代替next数组,从左到右扫描next数组,重复出现的字符的nextval值与它第一次出现相同,减少重复的比较。  即如果出现模式串中此次匹配失败位置j的字符和失败后跳至next[j]位置的字符相等T(next[j])=T(j)时,需要再次递归,将next[j]修正为next[next[j]],直至两者不相等为止,以此减少无意义的比较。

  if(T[i]!=T[j])  nextval[i]=j;
  else   nextval[i]=nextval[j];

点个关注不迷路!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值