28.找出字符串中第一个匹配项
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。示例 1:
输入:haystack = “sadbutsad”, needle = “sad” 输出:0 解释:“sad” 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。 示例 2:输入:haystack = “leetcode”, needle = “leeto” 输出:-1 解释:“leeto” 没有在
“leetcode” 中出现,所以返回 -1 。提示:
1 <= haystack.length, needle.length <= 104 haystack 和 needle
仅由小写英文字符组成
思路 一
朴素匹配
顾名思义最简单的匹配方式但是时间复杂度较高
首先将字符串通过toCharArray
函数转为数组
for循环定义 i 指针指向hayStack数组的起始位置,索引在 [0 ~ (n - m + 1)]内遍历
嵌套while循环 如果字符匹配则 a ,b 指针继续同时向前
直到b = m或者 指针指向的内容不相同
最后返回 i 指针
class Solution {
public int strStr(String haystack, String needle) {
int n = haystack.length();
int m = needle.length();
//字符串转成数组
char[] hay = haystack.toCharArray();
char[] ned = needle.toCharArray();
for (int i = 0; i <= n - m; i++){
int a = i, b = 0;
while (b < m && hay[a] == ned[b]){
++a;
++b;
}
//如果能够完全匹配。返回原串的发起点下标
if(b == m) return i;
}
return -1;
}
}
思路二
KMP算法
没啥好说的,写原理的帖子很多
当模版背下来就好
class Solution {
//KMP算法,源串为 string, 匹配串为pattern
//不管何时,string的指针不回溯
//pattern的指针有条件地回溯
public int strStr(String haystack, String needle) {
if (needle.length() == 0) return 0;
int[] next = new int[needle.length()];
getNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
while (j > 0 && needle.charAt(j) != haystack.charAt(i))
//j指针回溯
j = next[j - 1];
if (needle.charAt(j) == haystack.charAt(i))
j++;
if (j == needle.length())
return i - needle.length() + 1;
}
return -1;
}
//寻找nxet数组
private void getNext(int[] next, String s) {
int j = 0;
next[0] = 0;
for (int i = 1; i < s.length(); i++) {
while (j > 0 && s.charAt(j) != s.charAt(i))
//如果 s.charAt(j) 和 s.charAt(i) 不相等,说明当前位置匹配失败,需要回溯到前一个可能匹配的位置,即 j = next[j - 1]。
j = next[j - 1];
//如果 s.charAt(j) 和 s.charAt(i) 相等,说明找到了一个更长的重复前缀和后缀,将 j 的值增加 1。
if (s.charAt(j) == s.charAt(i))
j++;
//将 j 的最新值赋给 next[i],表示在位置 i 处的字符之前的最长重复前缀和后缀的长度。
next[i] = j;
}
}
}
NEXT数组演示