文章目录
6. 字符串 - 串存储结构及KMP算法
6.1 字符串基本概念
串结构
是用于存储字符类型
的数据的线性存储结构- 根据串中存储字符的数量及特点,对一些特殊的串进行了命名和分类:
空串
:存储 0 个字符的串,例如S = ""
(双引号紧挨着)空格串
:只包含空格字符的串,例如S = " "
(双引号包含 5 个空格);子串和主串
:假设有两个串 a 和 b,如果 a 中可以找到几个连续字符组成的串与 b 完全相同,则称 a 是 b 的主串,b 是 a 的子串,字串又称为模式串。子串在主串中的位置
:指的是子串首个字符在主串中的位置。
6.2 串存储结构实现方法
存储一个字符串,数据结构包含以下 3 种具体存储结构:
6.2.1 定长顺序存储
定长顺序存储
:实际上就是用普通数组(又称静态数组)存储。- 例如 :
char str[22] = "Nothing is impossible!";
6.2.3 堆分配存储
堆分配存储
: 其实现方式是采用动态数组来存储字符串- 堆区的内存空间需要手动使用
malloc()
函数申请,并且在不用后要手动通过free()
函数将其释放,该函数库头文件为#include <stdlib.h>
- 例如 :
char * str = (char*)malloc(5*sizeof(char));
6.2.3 块链存储
串的块链存储
:即使用链表结构
存储字符串- 例如:
#define linkNum 3 // 全局设置链表中每个节点存储字符的个数
typedef struct Link {
char a[linkNum]; // 数据域可存放 linkNum 个字符数据
struct Link * next; // 代表指针域,指向直接后继元素
}link;
6.3 串的模式匹配算法
串的模式匹配算法
:是一种用来判断两个串之间是否具有"主串与子串"关系的算法- 实现串的模式匹配的算法主要有以下两种:
BF算法
:普通的模式匹配算法KMP算法
:快速模式匹配算法
6.3.1 BF算法 - 普通模式匹配算法
- 普通模式匹配算法,其实现过程没有任何技巧,就是简单粗暴地
拿一个串同另一个串中的字符一一比对
,得到最终结果 - 该算法
最理想的时间复杂度 O(n)
,n 表示串 A 的长度,即第一次匹配就成功。最坏情况的时间复杂度为 O(n*m)
,n 为串 A 的长度,m 为串 B 的长度。
#include <stdio.h>
#include <stdlib.h>
#include<stdint.h>
// 串普通模式匹配算法的实现函数
int BF_Mate(char* leadstr, char* matestr) {
int i = 0, j = 0;
int leadstrlen = strlen(leadstr);
int matestrlen = strlen(matestr);
while (i < leadstrlen && j < matestrlen) {
if (leadstr[i] == matestr[j]) {
i++;
j++;
}
else {
i = i - j + 1;
j = 0;
}
}
// 跳出循环有两种可能 :
// (1) i = leadstrlen, 说明已经遍历完主串, 匹配失败;
// (2) j = matestrlen, 说明子串遍历完成, 在主串中成功匹配
return j == matestrlen ? (i - j) : 0;
}
int main() {
char lead[] = "abaabababbababaabaabaababbbababaabaabaaabbaba";
char mate[] = "abaabaabaaabbaba";
printf("BF算法匹配结果为 :%d\n", BF_Mate(lead, mate));
return 0;
}
6.3.2 KMP算法 - 快速模式匹配算法
- KMP算法难度系数较大,其实现函数如下:
#include <stdio.h>
#include <stdlib.h>
#include<stdint.h>
// Next数组求解
void Next(char* matestr, int* next) {
next[0] = -1;
int i = 0;
int j = -1;
int matestrlen = strlen(matestr);
while (i < matestrlen - 1) {
if (j == -1 || matestr[i] == matestr[j]) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
}
int KMP_Mate(char* leadstr, char* matestr) {
int i = 0, j = 0;
int leadstrlen = strlen(leadstr);
int matestrlen = strlen(matestr);
int *next = (int*)malloc(matestrlen *sizeof(int));
Next(matestr, next);// 根据模式串, 求解next数组
printf("next =");
for (int t = 0; t < matestrlen; t++) {
printf(" %d", next[t]);
}
printf("\n");
while (i < leadstrlen && j < matestrlen) {
if (j == -1 || leadstr[i] == matestr[j]) {
i++;
j++;
} else {
j = next[j];
}
}
return j == matestrlen ? (i - j) : 0;
}
int main() {
char lead[] = "abaabababbababaabaabaababbbababaabaabaaabbaba";
char mate[] = "abaabaabaaabbaba";
printf("KMP算法匹配结果为 :%d\n", KMP_Mate(lead, mate));
return 0;
}
感谢阅读 若有错误 敬请见谅!!!