KMP 算法
基本概念
- S:文本串
- P:模式串
- next 数组:
next[i]
表示当模式串中第 i 个字符与文本串中某个字符不匹配时,模式串应该跳到文本串的哪个位置继续匹配。
next 数组含义及计算
对于模式串P
,next[i]
表示P[1 ... i-1]
这个子串的最长相同前后缀的长度。也就是说,如果P[i]
与文本串S
的某个字符不匹配,那么我们可以将P
向右移动next[i]
个位置,使得P[1 ... next[i]]
与P[i-next[i] ... i-1]
对齐,继续比较P[next[i]]
与S
的下一个字符。这样可以避免重复比较已经匹配的部分,提高效率。
next 数组的求法是通过模板串自己与自己进行匹配操作得出来的
// 计算next数组
for(int i = 2; j = 0; i <= m; i++) {
// 匹配不成功
while(j > 0 && p[i] != p[j+1]) {
j = next[j];
}
// 匹配成功
if(p[i] == p[j+1]) j++;
next[i] = j;
}
匹配过程
// 匹配
for(int i = 1, j = 0; i <= n; i++) {
// 匹配不成功
while(j > 0 && s[i] != p[j+1]) {
j = next[j];
}
// 匹配成功
if(s[i] == p[j+1]) j++;
// 匹配完成
if( j == m ) return i - m;
}
LeetCode-28.找到字符串中第一个匹配项的下标
题目描述
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
程序代码
class Solution {
public:
int strStr(string haystack, string needle) {
int n = haystack.size(), m = needle.size();
string s = " " + haystack;
string p = " " + needle;
vector<int> next(m + 1, 0);
// 计算next数组
for(int i = 2, j = 0; i <= m; i++) {
// 匹配不成功
while(j > 0 && p[i] != p[j+1]) {
j = next[j];
}
// 匹配成功
if(p[i] == p[j+1]) j++;
next[i] = j;
}
// 匹配
for(int i = 1, j = 0; i <= n; i++) {
// 匹配不成功
while(j > 0 && s[i] != p[j+1]) {
j = next[j];
}
// 匹配成功
if(s[i] == p[j+1]) j++;
// 匹配完成
if( j == m ) return i - m;
}
return -1;
}
};