“抽象”《大话数据结构》第五章——串

串的定义

串是由零个或者多个字符组成的有限序列,又名叫做字符串。
子串:串中任意个数的连续字符组成的子序列称为该串的子串。
空串:零个字符串的串,长度为零。
空格串:由空格组成,有长度。

串的比较

相等:必须是他们串的长度以及它们各个对应位置的字符都相等。
不相等时:1 字符串的长度不相同。2 有s = “a1 a2 a3…an”,t = “b1 b2 … bm”,存在某个k < = min(n m),使得ai = bi (i = 1,2,3…k-1), ak < bk或者ak > bk。

串的抽象数据类型

串的数据:一串字符串,每个元素仅由一个字符组成。
串的操作: 1 查找子串的位置。2 得到指定位置的子串。 3替换子串。4 返回串的长度。5 指定位置插入子串。 6 指定位置删除一定长度的子串。

串的存储结构

串的顺序存储结构

串的顺序存储结构是用一组地址连续的存储单元来存储串中的字符序列的,一般用定长数组来实现,下标为0的存储位置用来存储串的长度。
下面看看顺序存储结构下,若主串中存在和查找串相同的子串,则返回子串的位置,用代码如何实现:
1 分别得到主串S和子串T的长度。
2 从下标为1的元素位置开始比较。
3 在位置pos不超过 S - T + 1 的情况下不断比较,(若超过,则取不出长度为T的子串啦)
4 从主串中取出与T相等长度的子串与之比较,不行等则加一。
5 相等则返回位置。

int String_Index(String S, String T,int pos)
{
	int n,m,i;
	String sub;
	if(pos > 0)
	{
		n = StrLength(S);
		m = StrLength(T);
		i = pos;
		while(i < n-m + 1)
		{
			SubString(sub,S,i,m);
			if(StrCompare(sub,T) != 0)
				i++;
			else
				return i;
		}
	}
	return 0;
}

串的链式存储结构

与线性表类似,但是每个节点的数据域不止存储一个字符。

朴素的模式匹配算法

这其实是在顺序存储结构下实现的,设计流程如下:
1 传入 S 和 T
2 定义 i 为主串S循环计数器,定义 j 为T的循环计数器
3 判断 i < ( S[0] - T[0] + 1 )且 j < T[0]
4 若S[i] == T[j],则i和j分别后移
5 若S[i] != T[j],则 i = i - j + 2,j = 1,重新计数
6 判断完整的比较完毕,返回在主串上的位置
代码如下:

int String_Index(String S, String T,int pos)
{
	int i,j;
	i = pos;
	j = 1;
	while(i < (S[0] - T[0] + 1) && j < T[0])
	{
		if(S[i] == T[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 2;
			j = 1;
		}
	}
	if(j > T[0])
		return i - T[0];
	else
		return 0;
}

KMP模式匹配算法

对于一些自身有重复的子串的主串 T[j] 来说,有些比较是没必要的,也就是说 j 没有必要总是回溯到1.下面我们需要推导在朴素比较法下,第一轮比较结束后,这时得到刚刚结束自加的 j ,进入下一轮比较前,j需要变化多少,由于常常比较的主串S是不一样的,所以第一轮结束后 j 的值会不一样,所以需要根据串T推导并记录每个 j 在进入下一轮比较前需要变为多少,存储在NEXT[j]里面。
下面看看KMP模式匹配算法实现的思想:
1获取T的next数组

在这里插入图片描述
由书上描述:next[Bigcycle]里面的值是由第Bigcycle个字符前面的字符串的前缀和后缀的相似度决定的。
故:若第Bigcycle个字符前的字符串均都相同,则一直执行黑色大循环,next[Bigcycle]一直变大。
若出现T[Bigcycle] != T[Smallcycle],则执行红色循环,Smallcycle回溯,再次判断T[Bigcycle] ?= T[Smallcycle] ,不相等则继续回溯,知道Smallcycle == 0,又能进入大的黑色循环。
代码如下:

void get_next(String T, int *next)
{
	int Bigcycle,Smallcycle;
	Bigcycle = 1;
	Smallcycle = 0;
	next[1] = 0;
	while(Bigcycle < T[0])
		{
			if(Smallcycle == 0 || T[Bigcycle] == T[Smallcycle])
				{
					Smallcycle++;
					Bigcycle++;
					next[Bigcycle] = Smallcycle;
				}
			else
				Smallcycle = next[Smallcycle];
		
		}
	
}

接下来就需要用该函数将朴素模式比较法改进成为KMP模式比较:
代码思路如下:
1 定义一个合适长度的数组,将获取的字符存储起来。
2 在不超过T[0]长度和小于S[0] - T[0] + 1的情况下执行循环
3 记录主串比较位置的 i 是不回溯的,而记录子串也记录T的比较位置,在T[j] != S[I]时,j需要按照next数组的值回溯。
4 比较结束后,需要返回位置的值:i - T[0]
代码如下:

int Index_KMP(String S,String T,int pos)
{
	int i, j;
	i = pos;
	j = 1;
	int next[255];
	get_next(T, next);
	while(i < (S[0] - T[0] + 1) && j < T[0])
		{
			if(j == 0 || S[i] == T[j])
				{
					i++;
					j++;
				}
			else
				j = next[j];
		}
	if(j > T[0])
		return i - T[0];
	else
		return 0;
}

KMP模式匹配算法改进

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值