#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
void GetNext(char* arr2, int* next)//arr2为字串
{
int i = 0;
int k = -1;
int len2 = strlen(arr2);
next[0] = -1;
while (i < len2)
{
if (k == -1 || arr2[i] == arr2[k])//k==-1时有两种情况:第一种是一开始k就为-1,第二种是k=-1是不能再回溯。
{
k++;//若相等则k一定只加1
i++;//子串往后移一位里放next的值
next[i] = k;//放入next的值
}
else
{
k = next[k];//字符不同则回溯
}
}
}
void GetNext_Pro(char* arr2, int* next)
{
int i = 0;
int k = -1;
int len2 = strlen(arr2);
next[0] = -1;
while (i < len2)
{
if (k == -1 || arr2[i] == arr2[k])
{
k++;
i++;
if (arr2[i] == arr2[k])//进入第一个if语句后向后一位的字符该arr2[i]与arr2[k]仍然相等则直接一次性回溯到位
{
next[i] = next[k];
}
else //arr2[i] != arr2[k]
{
next[i] = k; //不用多次回溯,跟next数组一样
}
}
else
{
k = next[k];
}
}
}
int KMP(char* arr1, char* arr2,void Next_Get(char* , int* )) //arr1为主串,arr2为字串
{
assert(arr1 && arr2); //保证传入的指针不是空指针
int len1 = strlen(arr1);
int len2 = strlen(arr2);
if (len2<0 || len2>len1)
{
return -1;
}
if (len1 == 0 || len2 == 0) //两种不可能的情况
{
return -1;
}
int* next = (int*)malloc(sizeof(int) * len2);//为next数组动态开辟空间
Next_Get(arr2, next);
for(int i = 0;i < len2;i++)
{
printf("%d ",next[i]);
}
printf("\n");
int i = 0;
int j = 0;
while (i < len1 && j < len2)
{
if(j == -1)
{
i++;
j = 0;
}
if (arr1[i] == arr2[j])//比较相等均后移一位
{
i++;
j++;
}
else
{
j = next[j];//不相等则回溯子串,主串不动
}
}
if (j >= len2)
{
return i - j;//返回主串与字串开始匹配到成功的开始位置
}
return -1;//子串与主串没有可匹配的字符串
}
int main()
{
char arr1[] = "abaaaababc";
char arr2[] = "aaaaba";
printf("%d\n", KMP(arr1, arr2,GetNext_Pro));
printf("%d\n", KMP(arr1, arr2,GetNext));
return 0;
}
KMP算法
最新推荐文章于 2024-09-27 14:28:55 发布