04. 串
4.1 概述
4.1.1 串的定义和基本操作
术语
- 长度:串中字符的数目 n n n
- 子串:串中任意个连续的字符组成的子序列
- 主串:包含子串的串
- 字符在主串中的位置:字符在串中的序号
- 子串在主串中的位置:子串的第一个字符在主串中的位置
4.1.2 串的存储结构
-
顺序存储
-
静态数组实现(定长顺序存储)
c# define MAXLEN 255 // 预定义最大串长 255 typedef struct{ char ch[MAXLEN]; // 每个分量存储一个字符 int length; // 串的实际长度 }SString;
-
动态数组实现(堆分配存储)
typedef struct{ char *ch; // 按串长分配存储区,ch指向串的基地址 int length; // 串的实际长度 }HString; HString S; S.ch = (char *)malloc(MAXLEN * sizeof(char)); S.length = 0;
-
-
链式存储
-
存储密度低
typedef struct StringNode{ char ch; struct StringNode * next; }StringNode,*String;
-
存储密度高
typedef struct StringNode{ char ch[4]; // 每个结点存多个字符 struct StringNode * next; }StringNode,*String;
-
4.2 模式匹配
4.2.1 朴素模式匹配算法
// 使用基本操作
int Index(SString S,SString T){
int i = 1,n = StrLength(S), m = StrLength(T);
SString sub;
while(i <= n - m + 1){ // 最多对比 n-m+1 个子串
SubString(sub,S,i,m); // 取出从位置i开始,长度为m的子串
if(StringCompare(Sub,T)!=0)
++i;
else
return i;
}
return 0;
}
// 不使用基本操作
// 时间复杂度:O(S.length * T.length)
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 + 2;
j = 1;
}
}
if(j > T.length)
return i - T.length;
else
return 0;
}
4.2.2 KMP算法
4.2.3 KMP算法的进一步优化
nextval[1] = 0;
for(int j = 2;j <= T.length; j++){
if(T.ch[next[j]] == T.ch[j])
nextval[j] = nextval[next[j]];
else
nextval[j] = next[j];
}