第五章 串
定义:串是由零个或多个字符串组成的有限序列,又叫字符串。
子串和主串:串中任意个数的连续字符组成的子序列称为该串的子串,相应的包含子串的串称为主串。
字串在主串中的位置就是子串的第一个字符在主串中的序号。
串的比较:串的比较是通过串的字符之间的编码来进行的。
串的抽象数据类型:
串的存储结构
串的顺序存储结构:用一组地址连续的存储单元来存储串中的字符序列。
可能会在第一个或最后一个元素中存放长度,也可能在最后添加\0
固定长度的缺陷:固定后可能出现上溢提示或者截断,这时用"堆"来处理更好,堆可以用C语言的malloc()和free()来管理。
串的链式存储结构:结构中的每个数据元素都是一个字符,但是只放一个会很浪费,因此一个系欸但也可以存放多个字符,如果最后一个结点没有被占满的话,可以用#补全。
链式缺陷:一个结点存放多少个字符才合适变得很重要,这会直接影响串的处理效率,需要根据实际情况做出选择。
两种对比:链式除了连接串与串操作时有一定方便之外,总的来说不如顺序存储灵活,性能也不如顺序存储结构好。
朴素的模式匹配算法
串的模式匹配:像寻找一个单词在一篇文章中的定位问题,这种子串的定位操作通常称为串的模式匹配。
子串寻找例题:
// 返回子串T在主串S中第pos个字符之后的位置,不存在则返回0
// T非空,1 <= pos <= StrLength(S)
// 设字符串的长度存放在第一个位置中
int Index(String S, String T, int pos)
{
int i = pos; // 匹配开始的位置
int j = 1; // 用来记录子串中的下标
while (i<=S[0] && j<=T[0])
{
if (S[i] == T[j])
{
i++;
j++;
}
else // 出现不相等的情况了
{
i = i - j + 2; // 回到刚才的位置的后面
j = 1; // 重置T的位置
}
}
if (j > T[0]) // 说明走完了T全部,匹配
return i - T[0];
else
return 0;
}
时间复杂度分析:
- 最好情况下,每次子串第一个就能检测出是否匹配,然后根据等概率原则,平均是(n+m)/2次查找,时间复杂度为O[n+m]。
- 最坏情况下,每次要找到子串最后一个才知道是否匹配,要执行 ( n − m + 1 ) ∗ m (n-m+1)*m (n−m+1)∗m次。时间复杂度为O[ ( n − m + 1 ) ∗ m (n-m+1)*m (n−m+1)∗m]
性能:低效。
KMP模式匹配算法
算法原理:
如果串中元素都不相同,那么可以跳过比较的长度,如下图可省略2-5步骤:
如果有相同的,那么相同的,可以在断掉的前面的那个相同除,如在45处直接取结果,省了一部分比较,其中2-5步骤是多余的: