串的定义
串(String) —— 零个或多个任意字符组成的有限序列
几个术语:
- 子串:串中任意个连续字符组成的子序列成为该串的子串
- 真子串:是指不含自身的所有子串
- 主串:包含子串的串相应地称为主串
- 字符位置:字符在序列中的序号为该字符在串中的位置
- 子串位置:子串第一个字符在主串中的位置
- 空格串:由一个或多个空格组成的串,与空串不同
- 串相等:当且仅当两个串的长度相等并且各个对应位置上的字符都相同时,这两个串才是相等的
串的类型定义
串的存储结构
串的顺序存储结构
#define MAXLEN 255
typedef struct{
char ch[MAXLEN + 1]; //存储串的一维数组
int length; //串的当前长度
}SString;
PS:串的下标为0 ~ 255,一般0号位闲置,用1 ~ 255,在研究算法时会带来一些简便
串的链式存储结构——块链结构
#define CHUNKSIZE 80 //块的大小可由用户自定义
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *head, *tail; //串的头指针和尾指针
int curlen; //串的当前长度
}LString; //字符串的块链结构
串的模式匹配算法
算法目的:
确定主串中所含子串(模式串)第一次出现的位置(定位)
算法应用:
搜索引擎、拼写检查、语言翻译、数据压缩
算法种类:
- BF算法(Brute-Force,又称古典的、经典的、朴素的、穷举的)
- KMP算法(特点:算法快)
BF(Brute-Force)算法
Brute-Force简称BF算法,亦称简单匹配算法。采用穷举法思路
算法思路:
从S的每一个字符开始依次与T的字符进行匹配
BF算法描述:
//pos - position,从某个位置开始查找
int Index_BF(SString S, SString T, int pos){
int i = pos, j = 1;
while(i <= S.length && j <= T.lenth){
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; //模式匹配不成功
}
BF算法时间复杂度为O(n*m)
KMP(Knuth Morris Pratt)算法
KMP算法是D.E.Knuth、J.H.Morris和V.R.Pratt共同提出的,简称KMP算法
详细讲解: https://www.bilibili.com/video/BV1jb411V78H.
KMP算法描述:
int Index_KMP(SString S, SString T, int pos){
i = pos, j = 1;
while(i < S.length && j < T.length){
if(j == 0 || S.ch[i] == T.ch[j]){
i++;
j++;
}
else
j = next[j]; //i不变,j后退
}
if(j > T.length)
return i - T.length; //匹配成功
else
return 0; //匹配失败
}
void get_next(SString T, int &next[]){
i = 1;
next[1] = 0;
j = 0;
while(i < T.length){
if(j == 0 || t.ch[i] == T.ch[j]){
++i;
++j;
next[i] = j;
}
else
j = next[j];
}
}