28. 找出字符串中第一个匹配项的下标

题目描述

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

解题思路

KMP 对我来说太烧脑了,不得不写点笔记

KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了

前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。

后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。

因为前缀表要求的就是相同前后缀的长度

定义两个指针i和j

  • j指向前缀末尾位置(不包含)
  • i指向后缀末尾位置(包含)

next[i] 表示 i(包括i)之前最长相等的前后缀长度(其实就是j)

void getNext(int* next, const string& s){
    int j = -1;
    next[0] = j;
    for(int i = 1; i < s.size(); i++) { // 对当前字符串,j指向上一个字符串的最大前后缀的位置
        while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
            j = next[j]; // 向前回退
        }
        if (s[i] == s[j + 1]) { // 找到相同的前后缀
            j ++ ;
        }
        next[i] = j; // 赋值
    }
}

举例

     j
 aabaabaaf
         i
 012345678
  0 01234
#![allow(unused)]
fn main() {
struct Solution {}

impl Solution {
    pub fn str_str(haystack: String, needle: String) -> i32 {
        let n = needle.len();
        let mut next = vec![0; n];
        let hay = haystack.chars().collect::<Vec<char>>();
        let s = needle.chars().collect::<Vec<char>>();
        let mut j = 0;
        for i in 1..n {
            while j >= 1 && s[i] != s[j] {
                j = next[j - 1];
            }
            if s[i] == s[j] {
                j += 1;
            }
            next[i] = j;    // next 表示以i结尾的字符串最大前后缀长度
        }
        // dbg!(&next);
        // build next ok
        if n == 0 { return 0 }
        j = 0;
        for i in 0..hay.len() {
            // dbg!(i, j);
            while j >= 1 && hay[i] != s[j] {
                j = next[j - 1];
            }
            if hay[i] == s[j] {
                j += 1;
            }
            if j == n {
                return (i + 1 - n) as i32
            }
        }
        -1
    }
}
}

学习感想

还得学习复习

#![allow(unused)]
fn main() {
struct Solution {}
impl Solution {
    pub fn str_str(haystack: String, needle: String) -> i32 {
        if let Some(x) = haystack.find(&needle) {
            x as i32
        } else {
            -1i32
        }
    }
}

}