左神KMP算法 笔记
-
预处理阶段:创建部分匹配表。
- 这一阶段是对模式字符串的预处理。目的是创建一个表,表中的每个值表示模式字符串中,直到该位置为止的字符串段的前缀和后缀的最长公共元素长度。
- 例如,如果模式是 "ABCDAB", 部分匹配表会是 [0, 0, 0, 0, 1, 2]。这表示在第六个字符 'B' 处,有长度为 2 的相同前缀和后缀 "AB"。
-
搜索阶段:在文本中搜索模式。
- 在这一阶段,算法遍历文本字符串,尝试与模式字符串匹配。
- 当遇到不匹配的字符时,而不是简单地将模式字符串向右移动一位,算法使用部分匹配表来决定将模式字符串向右移动多远。这避免了对之前已经匹配的字符的重复检查。
- 移动的具体位数是根据部分匹配表中的值来确定的,这个值反映了可以在模式字符串中重用的已匹配字符的数目。
-
匹配或失败:
- 如果模式字符串完全匹配,则在文本中找到了一个匹配项。记录匹配位置或返回匹配信息。
- 如果到达文本字符串的末尾都没有找到完全匹配,则搜索失败。
next数组
next加速过程
加速核心
图解前面一定匹配不出
整体过程
时间复杂度
代码
vector<int> nextArray(const string& s) {
int m = s.size();
vector<int> ne(m, 0);
ne[0] = -1;
if (m == 1)
return ne;
ne[1] = 0;
int i = 2, cn = 0;
while (i < m) {
if (s[i - 1] == s[cn])
ne[i++] = ++cn;
else if (cn > 0)
cn = ne[cn];
else
ne[i++] = 0;
return ne;
}
}
int kmp(const string& s1, const string& s2) {
int n = s1.size();
int m = s2.size();
vector<int> ne= nextArray(s2);
int x = 0, y = 0;
while (x < n && y < n) {
if (s1[x] == s2[y]) {
x++;
y++;
}
else if (y == 0) {
x++;
}
else {
y = ne[y];
}
return y == m ? x - y : -1;
}
}