第四章 串

串的定义和实现

串的基本概念

串的定义

串,即字符串,是由零个或多个字符组成的有限序列,一般记为

\[S='a_{1}a_{2}a_{3}...a_{n}'(n\ge0) \]

其中,S是串名,单引号括起来的字符序列是串的值,\(a_{i}\)可以是字母、数字或其他字符:串中字符的个数n称为串的长度,\(n=0\)时的串称为空串(用\(\emptyset\)表示)

  • 子串:串中任意个连续的字符组成的子序列(子串在主串中的位置用子串的第一个字符在主串中的位置来表示)
  • 主串:包含子串的串
  • 字符在主串中的位置:字符在串中的序号
  • 空格串:由一个或多个空格组成的串称为空格串,其长度为串中空格字符的个数

当两个串的长度相等且每个对应位置的字符都相等时,称这两个串是相等的

串是一种特殊的线性表,数据元素之间呈线性关系

串的数据对象限定为字符集

串的基本操作。如增删改查等通常以子串为操作对象

串的实现

串的存储结构

定长顺序存储表示

用一组地址连续的存储单元来存储串值的字符序列,在串的定长顺序存储结构中,为每个串变量分配一个固定长度的存储区,即定长数组

#define MaxSize 255//预定义最大串长为255
typedef struct {
	char ch[MaxSize];//每个分量存储一个字符
	int length;//串的实际长度
} SString;

串的实际长度只能小于或等于MaxSize,超过预定长度的串值会被舍去,称为截断

堆分配存储表示

仍然以一组地址连续的存储单元存放串值的字符序列,但它们的存储空间是在程序执行过程中动态分配得到的

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

块链存储表示

由于串的特殊性(每个元素只有一个字符),在具体实现时3,每个结点既可以存放一个字符,又可以存放多个字符。每个结点称为块,整个链表称为块链结构

image

串的基本操作

StrAssign(&T,chars)//复制操作,把串T赋值为chars

StrCopy(&T,S)//复制操作,由串S复制得到串T

StrEmpty(S)//判空操作,若S为空串,则返回true,否则返回false

StrLength(S)//求串长,返回串S的元素的个数

SubString(&Sub,S,pos,len)//求子串,用Sub返回串S的第pos个字符起长度为len的子串

ClearString(&S)//清空操作,将串S清空为空串

DestroyString(&S)//销毁串,将串S销毁(回收存储空间)

Concat(&T,S1,S2)//串联接,用T返回由S1和S2联接而成的新串

Index)(S,T)//定位操作,若主串S中存在与串T相同的子串,则返回它在主串S中的第一次出现的位置,否则函数值为0

StrCompare(S,T)//比较操作,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0(逐个字符比较ASCII码)、

基本操作的实现

求子串

bool SubString(SString &Sub, SString S, int pos, int len) {
	//子串范围越界
	if (pos + len - 1 > S.length) {
		return false;
	}
	for (int i = pos; i < pos + len; i++) {
		Sub.ch[i - pos + 1] = S.ch[i];
	}
	Sub.length = len;
	return true;
}

比较操作

int StrCompare(SString S, SString T) {
	for (int i = 1; i <= S.length && i <= T.length; i++) {
		if (S.ch[i] != T.ch[i]) {
			return S.ch[i] - T.ch[i];
		}
	}
	//扫描过的所有字符都相同,则长度长的串更大
	return S.length - T.length;
}

串的模式匹配

在主串中找到模式串相同的子串,并返回其所在的位置

简单的模式串匹配算法(朴素模式匹配算法)

将主串中所有长度为m的子串依次与模式串对比,直到找到一个完全匹配的子串,或所有的子串都不必配为止

若当前子串匹配失败,则返回主串指针i指向下一个子串的第一个位置,模式串指针j回到模式串的第一个位置

缺点:当某些子串与模式串能部分匹配时,主串的扫描指针经常回溯,导致时间开销增加

int index(SString S, SString T) {
	int i = 1, j = 1;
	while (i <= S.length && j <= T.length) {
		if (S.ch[i] == T.ch[j]) {
			i++;
			j++;
		} else {
			i = i - j + 1;
			j = 1;
		}
	}
	if (j > T.length) {
		return i - T.length;
	} else {
		return 0;
	}
}

这主串长度为n,模式串长度为m,则最坏时间复杂度为O(nm)

串的模式匹配算法——KMP算法

串的前缀:包含第一个字符,且不包含最后一个字符的子串

串的后缀:包含最后一个字符,且不包含第一个字符的子串

部分匹配值则为字符串的浅灰和后缀的最长相等前后的长度

KMP算法:当子串和模式串不匹配时,主串指针i不回溯,模式串指针j=next[j]

算法平均时间复杂度:O(n+m)

next数组手算方法:当第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则:next[j]=S的最长相等前后缀长度+1

next[1]=0

posted @ 2025-12-09 22:04  Eulbo_1018  阅读(5)  评论(0)    收藏  举报