KMP 算法
KMP 算法 —— 用于字符串匹配。优点是在匹配的过程中不用回退主指针,子指针会根据子串中最长相等前后缀来进行回退,能够大大降低时间复杂度。
这里有几个定义需要说明:
- 前缀:不包含尾字符的所有子串
- 后缀:不包含首字符的所有子串
举例:T = aabaaf
子串 | 说明 | 最长相等前后缀的长度 |
---|---|---|
$t_1=\mathrm{a}$ | 无前缀也无后缀 | $\pi \left( 0 \right) =0$ |
$t_1=\mathrm{aa}$ | 前缀为 $\small {\mathrm {a}}$ 后缀也为 $\small {\mathrm {a}}$ | $\pi \left( 1 \right) =1$ |
$t_1=\mathrm{aab}$ | 前缀一定无 $\small {\mathrm {b}}$ 后缀一定有 $\small {\mathrm {b}}$ | $\pi \left( 2 \right) =0$ |
$t_1=\mathrm{aaba}$ | 最大相等前后缀为 $\small {\mathrm {a}}$ | $\pi \left( 3 \right) =1$ |
$t_1=\mathrm{aabaa}$ | 最大相等前后缀为 $\small {\mathrm {aa}}$ | $\pi \left( 4 \right) =2$ |
$t_1=\mathrm{aabaaf}$ | 无最大相等前后缀 | $\pi \left( 5 \right) =0$ |
$\mathrm{j}$ | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
$T$ | a | a | b | a | a | f |
$\pi(T)$ | 0 | 1 | 0 | 1 | 2 | 0 |
一般也把 $\small {\pi (T)}$ 叫做前缀表,前缀表中保存的元素就是子指针回退的位置。编程实现中,也叫 next 数组。具体计算如下:
void NextTable(vector<int>& next, string s) |
力扣 28
找出字符串中第一个匹配项的下标
这个题目就是一道经典的匹配问题,暴力解法同时遍历 haystack 和 needle,时间复杂度为 $\small {O (M * N)}$,空间复杂度为 $\small {O (1)}$:
int strStr(string haystack, string needle) |
如果用 KMP 算法,时间复杂度为 $\small {O (M + N)}$,空间复杂度为 $\small {O (M)}$。
int strStr(string haystack, string needle) |
可以发现 KMP 算法无论是创建前缀表还是应用前缀表,代码具有高度相似性。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 洛天的小窝!
评论