(自己做的笔记用)
主函数部分
定义了一个串的数据类型(按数据结构的话来说。。。)
typedef struct{
char ch[30];
int length;
}string;
int KMP(string sub_string, string main_string);
void GetNext(string sub_string, int next[]);
int main()
{
string main_string, sub_string;
strcpy(main_string.ch, "0abbcabbcaabbacbaabcbbcaab");
main_string.length = 25;
strcpy(sub_string.ch, "0bcabb");
sub_string.length = 5;
printf("%d", KMP(sub_string, main_string));
return 0;
}
KMP算法的一大难点,求出next数组,由此来优化模板串中会出现相同子串的情况,极大优化了时间复杂度。
int KMP(string sub_string, string main_string)
{
int next[9];
int i = 1, j = 0;
GetNext(sub_string, next);
while (i <= main_string.length && j <= sub_string.length)
{
if (j == 0 || main_string.ch[i] == sub_string.ch[j])
{
i++, j++;
}
else
{
j = next[j];
}
}
if (j > sub_string.length)
return i - j + 1;
else
return 0;
}
头疼的next数组:
这里是KMP算法最难理解的部分,这里建议使用图解来辅助理解。
对于next数组的求法,以下使用了很短的代码,却实现复杂的操作。
我这里对next的理解便是:模板串的回溯接口。
对于next数组的求法,主要需要弄懂 j = next[ j ] 的作用,这里是起到回溯。
(对于初步理解,主要可以参考【天勤考研】KMP算法易懂版_哔哩哔哩_bilibili)
(对于next数组代码的理解建议去看B站KMP算法之求next数组代码讲解_哔哩哔哩_bilibili)
void GetNext(string sub_string, int next[]) //KMP算法的核心
{
next[1] = 0;
int i = 1, j = 0;
while (i <= sub_string.length)
{
if (j == 0 || sub_string.ch[i] == sub_string.ch[j])
next[++i] = ++j;
else
j = next[j]; //最反人类的地方!!!
}
}