参考书籍《数据结构第二版——严蔚敏》
笔记暂时纪录在这,后续如果有改进和修改会同步更新
大部分的说明性语言都在注释中
数据结构定义说明
#define MAXLEN 255
typedef struct {//串的顺序存储结构(常用)
char ch[MAXLEN + 1];//储存串的一维数组
int length;//串的当前长度
}SString;
/*串的链式存储结构*/
#define CHUNKSIZE 50 //一个节点中,串块的大小
typedef struct Chunk {
char ch[CHUNKSIZE];
struct Chunk* next;//指向下一个节点的指针
}Chunk;
typedef struct {
Chunk* head,*tail;//串的头指针和尾指针
int curlen;//当前串的长度
}LString;
然后是比较重要的两个串匹配算法,分别是暴力匹配和KMP算法
//数组和广义表没有代码,都是一些理解类型的知识,这里不在记录
int CmpStr_Index_BF(SString S, SString T, int pos);
int CmpStr_Index_KMP(SString S, SString T, int pos);
然后是这俩算法的具体实现思路,代码如下:
/**
* @brief 串的模式匹配算法(确定主串中子串第一次出现的位置)。
BF法(暴力破解法)
算法思路,依次在串中匹配,不符合就前移一位继续匹配,
直到匹配成功,或匹配到底结束(
匹配过程是一位一位匹配的如果第一位就不一样那就
往后移一位,继续匹配,和我开始想的方法差不多,异曲同工
果然无脑暴力)
* @param S:主串
* @param T:子串
* @param pos:从那个位置开始查找
* @retval 第一次出现的位置
*/
int CmpStr_Index_BF(SString S, SString T,int pos){
int i = pos, j = 1;
while(i<=S.length&&j<=T.length){//s或t串有一个扫完就退出循环
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;//没有匹配到
}
/*未优化的求next数组方法*/
void GetNext(SString T, int* next) {
next[1] = 0;
int j = 0;
int i = 1;
while (i < T.length) {
if (0 == j || T.ch[i] == T.ch[j]) {
i++, j++;
next[i] = j;
}
else {
j = next[j];
}
}
}
/*优化后的求next数组方法*/
void GetNext_UP(SString T, int* next) {
next[1] = 0;
int j = 0;
int i = 1;
//! 注意:while里面 不能写i<=T.length,因为如果这么写,那么i经过++后,i=T.length+1
//! 因为操作的内存是动态的,这样会导致内存泄漏
//! 所以必须是i<T.length,这样最后i才会指向T.length
while (i < T.length) {
if (0 == j || T.ch[i] == T.ch[j]) {
i++, j++;
//在未优化之前,如果ch[i]匹配失败,那么会回溯到ch[j]上
//如果ch[j] == ch[i]那么说明匹配仍然会失败,因为ch[i]匹配失败
if (T.ch[i] == T.ch[j]) {
//在i++,j++之后提前判断是否相等
next[i] = next[j];
}
else {
next[i] = j;
}
}
else {
j = next[j];
}
}
}
/**
* @brief 串的模式匹配算法(确定主串中子串第一次出现的位置)。
KMP算法
* @param S:主串
* @param T:子串
* @param pos:从那个位置开始查找
* @retval 第一次出现的位置
*/
int CmpStr_Index_KMP(SString S, SString T, int pos) {
int* next = (int*)malloc(sizeof(int) * (T.length + 1));
if (next) {//检查是否分配成功
GetNext_UP(T, next);
int i = pos;
int j = 1;
while (i <= S.length && j <=T.length) {
if (j == 0 || S.ch[i] == T.ch[j]) {
i++, j++;
}
else {
j = *(next+j);//有点大病,这里写成j=next[j]就报警告说可能越界,咋可能越界嘛
}
}
free(next);
if (j > T.length)
return i - j;
else
return 0;
}
return 0;
}