串知识点详解(数据结构,严蔚敏版)

本文介绍了基于堆分配存储表示的串操作函数实现,包括初始化、赋值、比较等,并详细解析了KMP算法中next函数及改进算法的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.堆分配存储表示(也是一种顺序表)

typedef struct{
	char *ch;
	int length;
}HString;

2.串操作函数


//初始化一个串
void InitalStr(HString &T);
//生成一个其值等于串常量chars的串T.
void StrAssign(HString &T, char *chars);
//返回串的长度
int StrLength(HString &T);
//比较串大小,从第一个开始比较,若T>S返回>0,若S=T 返回0;若T<S返回<0
int StrCompare(HString &T, HString &S);
//将T清空为空串
int ClearString(HString &T);
//用T返回S1和S2连接的新串
void Concat(HString &T, HString &S1, HString &S2);
//用Sub返回串T的第Pos个字符,长度为len的子串
int SubString(HString &Sub, HString &T, int pos, int len);

3.函数实现

#include<stdio.h>
#include<stdlib.h>
#include"HStringOp.h"
//初始化一个串
void InitalStr(HString &T){
	T.ch = NULL;
	T.length = 0;
}

//生成一个其值等于串常量chars的串T.
void StrAssign(HString &T,char *chars){
	int i = 0,j=0;
	char *c;
	if (T.ch)free(T.ch);
	for (i = 0, c = chars; *c; ++i, ++c);
	if (!i)
	{
		T.ch = NULL;
		T.length = 0;
	}
	else
	{
		if (!(T.ch = (char *)malloc(i*sizeof(char))))exit;
		while (j<i)
		{
			T.ch[j] = chars[j];
			j++;
		}
		T.length = i;
	}
}
//返回串的长度
int StrLength(HString &T){
	return T.length;
}
//比较串大小,从第一个开始比较,若T>S返回>0,若S=T 返回0;若T<S返回<0
int StrCompare(HString &T, HString &S){
	int i = 0;
	for ( i = 0; i < T.length&&i<S.length; i++)
	{
		if (T.ch[i]!=S.ch[i])
		{
			return T.ch[i] - S.ch[i];
		}
	}
	return T.length - S.length;
}
//将T清空为空串
int ClearString(HString &T){
	if (T.length == 0)return 1;
	free(T.ch);
	T.ch = NULL;
	T.length = 0;
	return 1;
}

//用T返回S1和S2连接的新串

void Concat(HString &T,HString &S1,HString &S2){
	if (T.ch)free(T.ch);
	if (!(T.ch=(char *)malloc((S1.length+S2.length)*sizeof(char))))exit;
	for (int i = 0; i < S1.length; i++)
	{
		T.ch[i] = S1.ch[i];
	}
	for (int i = S1.length; i < S1.length+S2.length; i++)
	{
		T.ch[i] = S2.ch[i-S1.length];
	}
	T.length = S1.length + S2.length;
}

//用Sub返回串T的第Pos个字符,长度为len的子串
int SubString(HString &Sub,HString &T,int pos,int len){
	if (!T.length)return 0;
	if (pos > T.length)return 0;
	if (Sub.ch)free(Sub.ch);
	if (T.length<(pos+len-1))Sub.length = T.length - pos + 1;
	else  Sub.length = len;
	
	Sub.ch = (char *)malloc(Sub.length*sizeof(char));
	for (int i = 0; i < Sub.length; i++)
	{
		Sub.ch[i] = T.ch[i + pos-1];
	}
	return 1;
}


4.子串位置定位一般算法,返回第pos个字符后子串的位置

int pos_substr(HString &F,HString &S,int pos){
	int i = pos, j = 0;
	int Flength = StrLength(F);
	int Slength = StrLength(S);
	if (Slength+pos>Flength)
	{
		return 0;
	}
	while (i<Flength&&j<Slength)
	{
		if (F.ch[i]==S.ch[j])
		{
			++i; ++j;
		}else
		{
			i=i-j+1; j = 0;
		}
		
	}
	if (j >=Slength)return i+1 - Slength;
	else  return 0;
}


5.KMP算法

(1)求next函数

//next函数求值
void get_next(HString &S,int *p){
	int i = 0, j = 0;
	i = 0; *p = 0;
	while (i<S.length-1)                //书中T[0]存放的是字符串的长度,我们这里T[0]也属于字符串的内容
	{
		/*
		实际上求next算法也是一个匹配的过程
		当ch[i]==ch[j-1]时说明,主串第i+1个(我们这里字符串从0开始)之前有j个字符与子串匹配。则p[i+1]=j;同时继续比较ch[i+1]=ch[j]
		当ch[i]!=ch[j-1]时说明,主串第i个字符与子串第j-1个字符适配,这时候需要获取子串的第j-1个next个值,再与主串进行比较
		这里表示next值的指针也是从0标号开始,与书上不同。
		*/
		if (j==0||S.ch[i]==S.ch[j-1]){   
			i++; j++;
			p[i] = j;
		}
		else
		{
			j = p[j-1];
		}
	}
}


求next函数改进算法

//KMP模式匹配改进算法
void get_nextval(HString &S, int *p){
	int i = 0, j = 0;
	i = 0; *p = 0;
	while (i < S.length - 1)                //书中T[0]存放的是字符串的长度,我们这里T[0]也属于字符串的内容
	{
		if (j == 0 || S.ch[i] == S.ch[j - 1]){
			i++; j++;
			if (S.ch[i]!=S.ch[j-1])
			{
				p[i] = j;
			}
			else{
				p[i] = p[j-1];
			}
		}
		else
		{
			j = p[j - 1];
		}
	}
}

(2)KMP实现定子串位置函数

//KMP模式匹配算法
int Index_KMP(HString T,HString S,int pos,int *p){
	int i = pos, j = 0;
	while (i<S.length&&j<T.length)
	{
		if (S.ch[i]==T.ch[j])
		{
			i++; j++;
		}
		else
		{
			j = p[j];
			if (j==0)
			{
				i++;
			}
			else
			{
				j--;
			}
		}
	}
	if (j>=T.length)
	{
		return i - T.length+1;
	}
	else
	{
		return 0;
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值