四、串的模式匹配

1.串和线性表的比较

从操作对象上看,串操作的对象是子串,而线性表操作的对象是单个数据元素;
从数据类型上看,串里存储的数据对象必须是字符集,而线性表内不要求数据类型;

2.串的大小比较

这里采用对应的ASCII值表来进行大小比较,从子串的第一个到最后一个字符依次进行比较,如果比较的两个串字符相同,另一个字符多增加了一个子串,那么长度更长的串更大。串的下标规定从1开始。

3.串的存储结构

存储结构可以采用顺序存储,也可以采用链式存储

  • 顺序存储,静态申请一片连续的存储空间,以王道书中给出的规范,第一个内存空间不存储任何元素,以便可以实现串的逻辑位置和物理位置上的对齐,在末尾增加一个空间用来存储串的长度。优点就是可以实现随机存取,而缺点在于不好扩充,因此必须采取必要的“截断”。
  • 链式存储,使用malloc函数动态分配内存空间(结束使用要free),每个结点包含一个数据域和next指针域,而数据域因为存储的是一个字符大小1B,而指针域要使用多余1B的空间来存储,在这样的情况下,是得不偿失的,所以采用块链存储。顾名思义就是将数据域的空间扩充,大于1B的意思(应该是这个意思),这样的好处显而易见,不浪费。使用链式存储的缺点就在于访问每个结点必须依次遍历。

4.串的模式匹配

4.1 朴素模式匹配
一种可以采用在主串里找模式串第一次出现的位置,类似于基本操作的定位子串的操作;
第二种方法是采用数组下标来找到对应的模式串;

  • 首先确定设置两个指针,一个用来扫描主串,一个用于扫描模式串,对主串一个字符一个字符进行扫描,主串每定位到一个字符,模式串就进行逐个扫描,假设最坏的情况是在最后一个字符的情况下才发现模式串和主串不匹配,那么以此类推,每一个子串的字符,模式串都要扫描至串尾,若主串长度尾n,模式串为m,那么时间复杂度为O(nm)。
int index(Sdtring S,Sstring T)
{
int i=1;//指向主串
int j=1;//指向模式串
	while(i<=S.length&&j<=T.length)
	{
		if(S.ch[i]==T.ch[j])
		{i++;j++}
		else
		{
			i=i-j+2;//调整指针位置,重新进行匹配,i和j的差值,等于将j回退到原来的起点,而-2相当于将其挪到下一次待匹配的位置
			j=1;
		}
		if(j>T.length)//j后+,所以不用等号
			return i-T.length;
	}
}

4.2 KMP算法匹配

简而言之,主要依靠next数组进行快速定位至下一个待匹配的位置,主串指针一直向前扫描,因此时间复杂度为O(n),只对模式串进行扫描,依照next数组给的位置确定下次从哪里开始继续匹配。缺点之一在于,如果扫描到一个不匹配的字符,那么在next数组中查找对应从哪个模式串下标开始匹配,假如,显示从下标为2的地方开始匹配,如果下标为2的地方字符和发生匹配失败的字符一样,那么下标为2的字符的位置也必然发生匹配失败,根据下标为2的字符给出的next数组转而去寻找其对于的下一个下标值,才可能匹配成功,如果下一个下标的字符和第一次匹配失败的字符又一样,那么还会失败,以此类推,这也是next数组可以优化改进的地方

  • 只对next数组改进,对源程序不做改动。将next数组中字符一样的next值修改成第一次发生错误的下标值,简而言之,就是将在next查下标值必然会发生错误的那些查找操作避免掉,一步到位到会成功的匹配下标。不一样的,next值不改变。
//KMP算法:
//主串一直向后扫描,只改变模式串指针的位置
//如果扫描到不同的字符,根据next数组值将j移到对应下标继续扫描

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只爱圣女果

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值