代码随想录算法训练营第九天|28.找出字符串中第一个匹配的下标
一. 字符串相关算法题
暴力双指针
思路
- 定义两个指针i,j分别指向两个字符串的起始位置,如果相等继续对比如果不等i从上次指针起始位置加1为起始点开始对比
- 直至j等于needle最后一个也相等返回或者i指向最后一个都没有找到全相等的返回-1;
构建next数组思路
- 定义i,j双指针:i指向后缀末尾,j指向前缀末尾
- 前后缀不相等处理:j回退到前缀数组上一位指向的下标
- 前后缀相等处理: j++,
- 每轮for循环:nex[i] = j;
class Solution {
public int strStr(String haystack, String needle) {
if (haystack.length()<needle.length()){
return -1;
}
int i = 0;
int lastIStart = i;
int j = 0;
while (j<needle.length()&&i<haystack.length()){
if (haystack.charAt(i)==needle.charAt(j)){
if (j==needle.length()-1){
return lastIStart;
}
j++;
i++;
}else {
j=0;
i=lastIStart+1;
lastIStart = i;
}
}
return -1;
}
}
kmp
- 求出每个子串的最长相等前后缀存入next数组中然后通过next数组回溯向下查找
- 可以避免上面暴力解法每次都要从头查找
- 时间复杂度O(n+m) :next数组O(m) + for循环查找: O(n)
- 空间复杂度 O(m)
class Solution {
public int strStr(String haystack, String needle) {
if (haystack.length()<needle.length()){
return -1;
}
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 = next[j-1];
}
if (needle.charAt(j) == haystack.charAt(i)){
j++;
}
if (j == needle.length()){
return i-needle.length()+1;
}
}
return -1;
}
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(i) != s.charAt(j)){
j = next[j-1];
}
if (s.charAt(j) == s.charAt(i)){
j++;
}
next[i] = j;
}
}
}