名词解释
https://baike.baidu.com/item/kmp%E7%AE%97%E6%B3%95/10951804?fr=aladdin (只看简介就行)。
算法原理
这个bili走一波,或者其他地方,有很多的讲解视频。(为啥是这样我也不懂,原理真的难懂,想出来的人好强。)
实现源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std; //写在一起只是个人习惯。
#pragma warning(disable:4996) //VS认为有的c函数不安全
//KMP算法
//计算前缀表
int* my_calPreFix(char* p, int len)
{
int* temp = (int*)malloc(sizeof(int) * len);
if (NULL == temp) {
return NULL;
}
*temp = -1; //前面这两个初始化是由KMP算法的原理决定的。
temp[1] = 0;
for (int i = 1; i < len - 1; i++)
{
int j = 0; //计算最长相同的个数
int k = i;
for (int m = 0; m < i; m++) {
if (p[m] == p[k]) {
j++;
k--;
}
else break;
}
temp[i + 1] = j;
}
return temp;
}
//字符串匹配
int my_kmp(char*t,int lent, char*p,int len)
{
int* temp = NULL;
temp = my_calPreFix(p,len);
for (int i = 0; i < lent;) { //对于主串T,仅需一次遍历。KMP的特点
for (int j = 0; j < len;) {
if (t[i] == p[j]) {
i++; j++;
}
else {
j = temp[j];
//如果,当前字符没匹配上,则模式串移动到相应位置。
//所谓的移动,也就是下标的改变,
//因为对字符串的访问,要靠下标。
//这也是KMP的灵魂,(个人觉得)
if (j == -1) {
//这是特例,j=-1时,没法移动。默认两个串都后移一位。
i++; j++;
}
}
if (j == len) {
return (i - len);
}
if (i == lent - len) {
return -1;
}
}
}
free(temp);
temp = NULL;
}
int main()
{
char str[1024] = { 0 };
char str1[1024] = { 0 };
char str2[1024] = { 0 };
scanf("%s", str);
scanf("%s", str1);
scanf("%s", str2);
int len = strlen(str);
int len1 = strlen(str1);
int len2 = strlen(str2);
int c = 0;
int d = 0;
c= my_kmp(str,len, str1,len1);
d = my_kmp(str,len,str2,len2);
/*int *p=my_calPreFix(str, len1);
for (int i = 0; i < len1; i++) {
cout << p[i] << endl;
}*/
//这是测试当时写的函数对不对,写一个函数测试一个函数是一个好习惯。继续保持。
cout << c << endl;
cout << d << endl;
return 0;
}
KMP算法到此结束,谢谢阅读。