1.题目
https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/
leetcode 28
字符串匹配之BF(Brute Force)算法是一种简单的字符串匹配算法,也叫暴力匹配算法。它的思想是将目标串 S 的第一个字符与模式串 T 的第一个字符进行匹配,如果相等,就继续比较 S 的第二个字符和 T 的第二个字符,如果不相等,就比较 S 的第二个字符和 T 的第一个字符,依次比较下去,直到找到一个匹配或者遍历完整个目标串
这个算法的时间复杂度是 O(mn) ,其中 m 和 n 是目标串和模式串的长度。空间复杂度是 O(1) ,因为不需要额外的空间
BF算法的优点是
简单易懂,实现起来不复杂,适用于短字符串的匹配。
BF算法的缺点是
效率较低,每次匹配失败时都要回溯主串和模式串的指针,导致大量的重复比较,时间复杂度为 O(nm) ,其中 n 是主串的长度,m 是模式串的长度。
2.解法
解法一:双指针,一个字符一个字符比较
这个实现的思想是定义一个指针 i 指向目标串 S 的当前位置,定义一个指针 j 指向模式串 T 的当前位置。每次比较 S[i] 和 T[j] ,如果相等,就让 i 和 j 都加一,继续比较下一个字符。如果不相等,就让 i 回退到上一次匹配的下一个位置,让 j 重置为 0 ,重新开始匹配。如果 i 超过了 S 的长度,或者 j 等于了 T 的长度,就结束循环。如果 j 等于了 T 的长度,说明找到了一个匹配,返回 i - j 作为匹配的起始位置。如果 i 超过了 S 的长度,说明没有找到匹配,返回 -1 作为标志。
public class StringBF { public static void main(String[] args) { String s = "leetcode"; String t = "tco"; System.out.println(bruteForce(s, t)); } public static int bruteForce(String s, String t) { int i = 0, j = 0; while (i < s.length() && j < t.length()) { if (s.charAt(i) == t.charAt(j)) { i++; j++; } else { i = i - j + 1; j = 0; } } if (j == t.length() ) { return i - j; } return -1; } }
解法二:滑动窗口+ subString 整体比较
思路
BF算法在 JDK 中有一些应用,比如 String 类的 indexOf() 方法和 lastIndexOf() 方法,都是使用 BF 算法来实现的。这些方法可以用来查找一个字符串中是否包含另一个字符串,或者返回一个字符串在另一个字符串中的位置
BF算法,也就是暴力匹配算法。它的基本思想是,从haystack的第一个字符开始,依次与needle的每个字符进行比较,如果都相等,就返回当前的索引;如果有不相等的,就从haystack的下一个字符开始,重复这个过程,直到找到匹配的子字符串或者遍历完haystack为止。
代码逻辑
- 首先,检查haystack和needle是否为空,如果是,就返回-1,因为这是一个无效的输入。
- 其次,检查haystack和needle是否相等,如果是,就返回0,因为这意味着needle就是haystack的第一个子字符串。
- 然后,获取needle的长度,用它作为滑动窗口的大小。
- 接着,从左到右遍历haystack,每次取出一个长度为needleLength的子字符串,与needle进行比较。
- 如果相等,就返回当前的索引i,表示找到了needle在haystack中的第一个位置。
- 如果不相等,就继续向右滑动窗口,直到遍历完整个haystack或者找到匹配的子字符串为止。
- 最后,如果遍历完haystack都没有找到匹配的子字符串,就返回-1,表示needle不是haystack的一部分。
具体实现
public class ImplementStrStr { public int strStr(String haystack, String needle) { // 基本条件 if (haystack == null || needle == null) { return -1; } // 特殊情况 if (haystack.equals(needle)) { return 0; } // needle的长度 int needleLength = needle.length(); // 遍历haystack并滑动窗口 for (int i = 0; i < haystack.length() - needleLength + 1; i++) { // 检查子字符串是否等于needle if (haystack.substring(i, i + needleLength).equals(needle)) { return i; } } return -1; } }
3.总结