数据结构 考研复试 突击
数据结构 备考第四天😂 串的模式匹配算法 KMP(未优化) vs 暴力解法。
关于KMP
- 个人理解,就是字串中有对称的串,若是这部分与主串匹配上的话,在之后的匹配失效后可以跳到字串对称的下个位置。
- 以面链接是王道数据结构的视频,KMP算法在P11视频有详细讲解😅。
王道视频KMP
附上截图:
附上代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LEN 100
typedef struct Result
{
int pos;
int time;
}Result;
// 粗暴法
void pm_rude(char str[], char sub[], Result *result)
{
int time = 0;
int i =0,j = 0;
int str_length = strlen(str); // 主串长度
int sub_length = strlen(sub); // 字串长度
while (i < str_length && j < sub_length)
{
if (str[i] == sub[j]) // 若值相等 都向i,j后移动
{
i++;
j++;
}
else
{
i = i - j + 1; // 回退 匹配失败的下个位置
j = 0;
}
time++;
}
if (j >= sub_length) // 若匹配成功返回 下标
{
result->pos = i - sub_length + 1;
}
else
{
result->pos = 0;
}
result->time = time;
}
// 计算next数组
void cal_next(char arr[], int *next)
{
int front=0, rear=1;
int arr_length = strlen(arr);
next[0] = 0; // 前缀为0
while (front < arr_length - 1 && rear < arr_length)
{
if (arr[front] == arr[rear])
{
front++; // 头指针移动
rear++; // 尾指针移动
next[rear-1] = front; // 记录上个节点的匹配度
}
else
{
if(front == 0)
{
rear++; // 此时front在0位置 不匹配的话 移动rear
}
else
{
front=0;
}
}
}
printf("next数组\n");
for (int i = 0; i < arr_length; i++)
{
printf("%d ", next[i]);
}
printf("\n");
}
// KMP算法 version 1
void pm_kmp_v1(char str[], char sub[], int next[], Result *result)
{
int str_length = strlen(str);
int sub_length = strlen(sub);
int str_p = 0;
int sub_p = 0;
result->time = 0; //初始化次数
cal_next(sub, next); // 计算next数组
while (str_p < str_length && sub_p < sub_length)
{
if (str[str_p] == sub[sub_p]) // 相等的话 同时向后移动
{
str_p++;
sub_p++;
}
else
{
if (sub_p == 0)
{
str_p++; // 若是 字串在0位置,移动主串
}
else
{
sub_p = next[sub_p-1]; // 将子串 更具上个 next数组 回溯
}
}
result->time++;
}
if (sub_p >= sub_length)
{
result->pos = str_p - sub_length + 1;
}
else
{
result->pos = 0;
}
}
int main()
{
Result *result1 = (Result*)malloc(sizeof(Result));
Result *result2 = (Result*)malloc(sizeof(Result));
char str[] = "cbacbacbabbcccabca";
char sub[] = "bacbabb";
// char str[] = "bbc abcdab abcdabcdabde";
// char sub[] = "abcdabd";
int next[LEN] = {-1};
pm_rude(str, sub, result1);
printf("位置暴力法:%d位置匹配,匹配次数:%d\n",result1->pos, result1->time);
pm_kmp_v1(str, sub, next, result2);
printf("KMP version1 法:%d位置匹配,匹配次数:%d\n",result2->pos, result2->time);
system("pause");
return 0;
}