【算法】实现indexOf()函数(KMP)

【算法】实现indexOf()函数(KMP)

2023年7月20日发(作者:)

【算法】实现indexOf()函数(KMP)题⽬实现 indexOf() 函数。给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第⼀个位置(下标从 0 开始)。如果不存在,则返回 -1 。说明:当 needle 是空字符串时,我们应当返回什么值呢?这是⼀个在⾯试中很好的问题。对于本题⽽⾔,当 needle 是空字符串时我们应当返回 0 。这与 C 语⾔的 strstr() 以及 Java 的 indexOf() 定义相符。⽰例 1:输⼊:haystack = “hello”, needle = “ll”输出:2⽰例 2:输⼊:haystack = “aaaaa”, needle = “bba”输出:-1⽰例 3:输⼊:haystack = “”, needle = “”输出:0提⽰:0 <= , <= 5 * 104haystack 和 needle 仅由⼩写英⽂字符组成朴素匹配直观的解法的是:枚举原串 ss 中的每个字符作为「发起点」,每次从原串的「发起点」和匹配串的「⾸位」开始尝试匹配:匹配成功:返回本次匹配的原串「发起点」。匹配失败:枚举原串的下⼀个「发起点」,重新尝试匹配时间复杂度 O(m * n)实现class Solution { public int strStr(String haystack, String needle) { int n = (), m = (); //

枚举原串的「发起点」 for (int i = 0; i < n - m + 1; i++) { boolean flag = true; //

从原串的「发起点」和匹配串的「⾸位」开始,尝试匹配 for (int j = 0; j < m; j++) { if ((i + j) != (j)) { flag = false; break; } } //

如果能够完全匹配,返回原串的「发起点」下标 if (flag) return i; } return -1; }}KMP解法KMP 算法是⼀个快速查找匹配串的算法,它的作⽤其实就是本题问题:如何快速在「原字符串」中找到「匹配字符串」。KMP的经典思想就是:当出现字符串不匹配时,可以记录⼀部分之前已经匹配的⽂本内容,利⽤这些信息避免从头再去做匹配。时间复杂度O(m+n)先看下「朴素匹配」逻辑:1. 将原串的指针移动⾄本次「发起点」的下⼀个位置(b 字符处);匹配串的指针移动⾄起始位置。2. 尝试匹配,发现对不上,原串的指针会⼀直往后移动,直到能够与匹配串对上位置也就是说,对于「朴素匹配」⽽⾔,⼀旦匹配失败,将会将原串指针调整⾄下⼀个「发起点」,匹配串的指针调整⾄起始位置,然后重新尝试匹配。然后我们再看看「KMP 匹配」过程:1. ⾸先匹配串会检查之前已经匹配成功的部分中⾥是否存在相同的「前缀」和「后缀」。如果存在,则跳转到「前缀」的下⼀个位置继续往下匹配2. 跳转到下⼀匹配位置后,尝试匹配,发现两个指针的字符对不上,并且此时匹配串指针前⾯不存在相同的「前缀」和「后缀」,这时候只能回到匹配串的起始位置重新开始到这⾥,你应该清楚 KMP 为什么相⽐于朴素解法更快:因为 KMP 利⽤已匹配部分中相同的「前缀」和「后缀」来加速下⼀次的匹配。因为 KMP 的原串指针不会进⾏回溯(没有朴素匹配中回到下⼀个「发起点」的过程)。可以预处理出

next 数组,数组中每个位置的值就是该下标应该跳转的⽬标位置(

next 点)。在实际编码时,通常我会往原串和匹配串头部追加⼀个空格(哨兵)。⽬的是让

j 下标从

0 开始,省去

j 从

-1 开始的⿇烦。//

构建 next

数组,数组长度为匹配串的长度(next

数组是和匹配串相关的)int[] next = new int[m + 1];//

构造过程 i = 2,j = 0

开始,i

⼩于等于匹配串长度

【构造 i

从 2

开始】for (int i = 2, j = 0; i <= m; i++) { //

匹配不成功的话,j = next(j) while (j > 0 && p[i] != p[j + 1]) j = next[j]; //

匹配成功的话,先让 j++ if (p[i] == p[j + 1]) j++; //

更新 next[i],结束本次循环,i++ next[i] = j;}实现在实际编码时,通常我会往原串和匹配串头部追加⼀个空格(哨兵)。⽬的是让

j 下标从

0 开始,省去

j 从

-1 开始的⿇烦。class Solution { // ss:

原串(string) pp:

匹配串(pattern) public int strStr(String ss, String pp) { if (y()) return 0;

//

分别读取原串和匹配串的长度 int n = (), m = (); //

原串和匹配串前⾯都加空格,使其下标从 1

开始 ss = " " + ss; pp = " " + pp; char[] s = Array(); char[] p = Array(); //

构建 next

数组,数组长度为匹配串的长度(next

数组是和匹配串相关的) int[] next = new int[m + 1]; //

构造过程 i = 2,j = 0

开始,i

⼩于等于匹配串长度

【构造 i

从 2

开始】 for (int i = 2, j = 0; i <= m; i++) { //

匹配不成功的话,j = next(j) while (j > 0 && p[i] != p[j + 1]) j = next[j]; //

匹配成功的话,先让 j++ if (p[i] == p[j + 1]) j++; //

更新 next[i],结束本次循环,i++ next[i] = j; } //

匹配过程,i = 1,j = 0

开始,i

⼩于等于原串长度

【匹配 i

从 1

开始】 for (int i = 1, j = 0; i <= n; i++) { //

匹配不成功 j = next(j) while (j > 0 && s[i] != p[j + 1]) j = next[j]; //

匹配成功的话,先让 j++,结束本次循环后 i++ if (s[i] == p[j + 1]) j++; //

整⼀段匹配成功,直接返回下标 if (j == m) return i - m; } return -1; }}

发布者:admin,转转请注明出处:http://www.yc00.com/news/1689847749a290265.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信