KMP算法

左神KMP算法 笔记

KMP算法_第1张图片

  1. 预处理阶段:创建部分匹配表。

    • 这一阶段是对模式字符串的预处理。目的是创建一个表,表中的每个值表示模式字符串中,直到该位置为止的字符串段的前缀和后缀的最长公共元素长度。
    • 例如,如果模式是 "ABCDAB", 部分匹配表会是 [0, 0, 0, 0, 1, 2]。这表示在第六个字符 'B' 处,有长度为 2 的相同前缀和后缀 "AB"。
  2. 搜索阶段:在文本中搜索模式。

    • 在这一阶段,算法遍历文本字符串,尝试与模式字符串匹配。
    • 当遇到不匹配的字符时,而不是简单地将模式字符串向右移动一位,算法使用部分匹配表来决定将模式字符串向右移动多远。这避免了对之前已经匹配的字符的重复检查。
    • 移动的具体位数是根据部分匹配表中的值来确定的,这个值反映了可以在模式字符串中重用的已匹配字符的数目。
  3. 匹配或失败

    • 如果模式字符串完全匹配,则在文本中找到了一个匹配项。记录匹配位置或返回匹配信息。
    • 如果到达文本字符串的末尾都没有找到完全匹配,则搜索失败。

next数组

KMP算法_第2张图片

next加速过程

加速核心

KMP算法_第3张图片

图解前面一定匹配不出

KMP算法_第4张图片

整体过程

时间复杂度

KMP算法_第5张图片

代码

vector nextArray(const string& s) {
	int m = s.size();
	vector 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 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;
	}
}

你可能感兴趣的:(数据结构)