串的定义和实现
串的基本概念
串的定义
串,即字符串,是由零个或多个字符组成的有限序列,一般记为
其中,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,每个结点既可以存放一个字符,又可以存放多个字符。每个结点称为块,整个链表称为块链结构

串的基本操作
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