2023年11月第三周总结
KMP算法
字符串查找算法中的经典算法,时间复杂度O(N + M),N是主串的长度,M是字串的长度。
int* get_next(char s[], int len) {
int* next = (int*)malloc(sizeof(int) * len);//netx数组的长度跟s2的长度一样
for (int i = 0; i < len; i ++) {//求每一个位置的next数组的值
if (i == 0) {//下标0位置规定是-1
next[i] = -1;
}
else if (i == 1) {//下标1位置一定是1
next[i] = 0;
}
else if (i == 2) {//下标2位置,就看下标0位置和下标1位置是不是相等的
next[i] = s[0] == s[1]? 1: 0;
}
else {//其他位置
int pre = i - 1;//要求位置的前一个位置,只跟要求的前一个位置有关
int k = next[pre];//要看的位置
while(k >= 0 && s[k] != s[pre]) {//如果没有看完整个字符串并且看的位置的字符和前一个位置的字符不匹配
k = next[k];//去下一个位置,因为要最大的前缀和后缀
}
next[i] = k + 1;//最后的答案就是k + 1,因为k = next[k],所以当k = -1时也成立
}
}
return next;//返回next数组
}
int kmp(char s1[], char s2[])
{
int s1_len = strlen(s1);//计算需要匹配的字符串的长度
int s2_len = strlen(s2);//计算字串的长度
if (s2_len > s1_len) {//如果字串的长度大于要匹配的字符串的长度
return -1;//直接返回-1,因为不可能匹配
}
int* next = get_next(s2, s2_len);//得到next数组
int x = 0;//在s1中对比的位置
int y = 0;//在s2中对比的位置
while(x < s1_len && y < s2_len) {//如果位置都没有越界
if (s1[x] == s2[y]) {//如果对比的位置匹配
x ++;//去下一个位置
y ++;//去下一个位置
}
else if (next[y] == -1) {//如果next[y] = -1代表以x开始匹配不出s2字符串了,所以去看s1中下一个位置
x ++;
}
else {//如果在s1中的x位置还可以匹配出s2来,就去看next[y]的位置继续匹配
y = next[y];
}
}
return y == s2_len? x - s2_len: -1;//如果是s2越界代表找到了,返回x - s2的位置,没有越界代表是s1越界了, 代表没有找到返回-1
}
int strStr(char* haystack, char* needle) {
return kmp(haystack, needle);
}
next数组也可以求字符串结束位置的next中的值,也就是看整个字符串,这个也是一样的,只是这个题目不用

浙公网安备 33010602011771号