LeetCode 28. 实现 strStr() (使用 KMP算法 )
题目地址:https://leetcode.cn/problems/implement-strstr/
参考:
https://www.bilibili.com/video/BV1AY4y157yL
https://www.bilibili.com/video/BV1PD4y1o7nd(推荐)
https://www.bilibili.com/video/BV1234y1y7pm
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串出现的第一个位置(下标从 0
开始)。如果不存在,则返回 -1
。
示例 1:
输入:haystack = "hello", needle = "ll"
输出:2
示例 2:
输入:haystack = "aaaaa", needle = "bba"
输出:-1
Solution
next
数组用于在匹配过程中发生冲突后模式串要回退到哪个位置。
next[i]
表示长度为 i + 1
的前缀子串的最长相同前后缀的长度。
// 传入目标串(模式串),求 next 数组
int* getNext(char *dst, int m) {
int *next = (int*) malloc(sizeof(int) * m);
memset(next, 0, sizeof(int) * m);
next[0] = 0; // next 数组 0 下标元素为 0
int j = 0;
// j 表示前缀指针,从头到尾移动(假设前缀的最右边为尾)
// i 表示后缀指针,从尾到头移动(假设后缀的最左边为尾)
for (int i = 1; i < m; i++) {
while (j > 0 && dst[i] != dst[j]) {
j = next[j - 1];
}
if (dst[i] == dst[j]) {
j++;
}
next[i] = j;
}
return next;
}
int strStr(char * src, char * dst){
int n = strlen(src), m = strlen(dst);
int *next = getNext(dst, m);
int j = 0;
// j 在匹配串上移动
// i 在原串上移动
for (int i = 0; i < n; i++) {
while (j > 0 && src[i] != dst[j]) {
j = next[j-1];
}
// 元素相同下标往后移动
if (src[i] == dst[j]) {
j++;
}
// j == m,j 走完匹配串,表示匹配完成,返回在原串上的起始下标
if (j == m) {
return i - j + 1;
}
}
return -1;
}